WordPress 4.9 in retrospect: the release before Gutenberg

WordPress 4.9 in retrospect: the release before Gutenberg

Last verified: October 14, 2026
14 min read
News
500+ WP projects

WordPress 4.9 “Tipton” (released in 2017) was a special release. It was the last major version before WordPress 5.0, which made Gutenberg the default editor.

Learn more about WordPress development services at WPPoland.

If you want the short version, WordPress 4.9 matters because it improved real editorial and developer workflows just before Gutenberg changed the entire editing model. This retrospective sticks to what the official release post, the 4.9 field guide on make.wordpress.org and the version page in the WordPress documentation actually say, with links so you can check each point.

#When was WordPress 4.9 released

WordPress 4.9 “Tipton”, named after jazz musician and band leader Billy Tipton, was announced on November 16, 2017 in the official release post. The version page in the WordPress documentation dates the release to November 15, which is the same moment seen from a US time zone. It was the last major version in which the classic editor was the default.

According to the release post, the release was led by Mel Choyce and Weston Ruter. It credits 443 contributors with props, 185 of them contributing for the first time, and it shipped fully translated into 43 languages. The documentation page adds two numbers that matter when you are inspecting an old install: the database version stayed at 38590, and the release corresponds to Trac revision 42195.

The 4.9 field guide published before the release counts roughly 400 bugs, 181 enhancements, 7 feature requests and 42 tasks closed in the cycle.

Why 4.9 matters in hindsight:

  • it was the last version where the classic editor was the default,
  • it brought CodeMirror into core, and that library still powers code fields in the dashboard,
  • it finished the Customizer changeset work started in 4.7,
  • its release post was itself written in Gutenberg and asked readers to test the new editor.

#What changed in the WordPress 4.9 Customizer

#Customizer drafts and scheduled changes

For the first time, you could make design changes (colors, CSS, widgets, menus), save them as a draft and come back later, without publishing anything live.

The plumbing was older than the button. Changesets, a way to store pending Customizer changes as a customize_changeset post identified by a UUID, arrived in WordPress 4.7. As Weston Ruter explains in the dev note on changesets in 4.9, 4.7 had no interface for them. A changeset sat in an auto-draft post that was garbage-collected after a week unless you kept touching it.

WordPress 4.9 added the interface. After the first change, a gear button next to Publish opens the publish settings, where you pick publish, save draft or schedule. A discard link resets the Customizer to its last published state.

Before 4.9, making design changes meant:

  • editing the live site (risky),
  • using a staging environment (more setup),
  • pasting CSS by hand (hard to revert).

Scheduling works because a changeset goes live when its post moves to the publish status. The dev note shows that the mechanism existed even before the interface, with a WP-CLI command that schedules a site title change:

wp post create \
    --post_type=customize_changeset \
    --post_name=$( uuidgen ) \
    --post_status=future \
    --post_date="2018-01-01 00:00:00" \
    --post_content='{"blogname":{"value":"Happy New Year!"}}'

One practical warning from the same note still applies. Scheduled changesets publish through WP-Cron, normally within a minute of the scheduled time. On a site with few visitors cron may not fire on time, and the note suggests a system cron job that pings wp-cron.php every minute when timing matters.

Previewing a changeset is a read-only operation, so anyone with the UUID can see the site with the pending changes applied, logged in or not. WordPress 4.9 turned that into a preview link you can send to colleagues and customers. The release post pitches it as a way to collect feedback before you schedule the changes to go live, which is how agencies used it.

#Design locking and autosave in the Customizer

Since a saved draft now loads for every user who opens the Customizer, two people could overwrite each other. The answer in 4.9 was changeset locking, modelled on post locking: a second user sees a locked notice and can go back or take over, and the Customizer uses WP Heartbeat to keep the lock alive.

Autosave also got friendlier. If you closed the browser by accident, the Customizer now offered to restore your most recent auto-draft the next time you opened it, and pages or posts created from the Customizer while drafting were marked as customization drafts in the admin list.

#Linear and branching changesets

Core runs in what the dev note calls linear mode: only one changeset can be saved as a draft or scheduled at a time. If you schedule a site title change for next week, you cannot publish an unrelated tagline change today without discarding or publishing both. Theme switching is also blocked while a draft or scheduled changeset exists.

Sites with several heavy Customizer users can restore the older behaviour, where each session gets its own changeset, with one filter:

add_filter( 'customize_changeset_branching', '__return_true' );

#Theme browsing and theme switching in the Customizer

The Customizer gained a new theme browser. The release post says you could search, browse and preview over 2,600 themes from inside the Customizer, with filters for subject, features and layout, and the field guide notes that you could install themes from WordPress.org in the same flow for the first time.

Switching themes also became less destructive. The documentation lists an “educated guess” mapping of nav menus and widgets (Trac #39692), so menus and widgets were more likely to stay in a sensible place on the new theme. The menu creation flow in the Customizer was reworked as well, with new instructions for creating a menu and assigning it to a location.

#How CodeMirror changed code editing in WordPress 4.9

Code editors in the dashboard finally got syntax highlighting, linting and auto-completion. The code editing dev note lists four places that received CodeMirror: Additional CSS in the Customizer, the Custom HTML widget, and the theme and plugin file editors.

It was a second attempt. Syntax highlighting in the file editors first appeared in WordPress 2.8 with a library called CodePress and was removed in 2.8.1 because of browser compatibility problems. The feature was re-proposed in Trac #12423 and took eight years to come back.

What CodeMirror added in 4.9:

  • Syntax highlighting with bundled modes including css, htmlmixed, javascript, php, sql, markdown and yaml.
  • Auto-closing and matching of brackets and tags.
  • Linting with CSSLint, JSHint, HTMLHint and JSONLint.
  • Auto-completion for CSS properties, HTML tags and JavaScript DOM objects.

When a linter finds an error, WordPress asks you to fix it before saving. In Additional CSS and the Custom HTML widget saving stays blocked until the code is valid; in the file editors you can override the warning and save anyway. In 4.7, Additional CSS only counted braces and brackets, which produced false positives when a brace sat inside a comment. That server-side check was removed in favour of CSSLint.

Two details show how carefully the change was scoped. CodeMirror was not added to the Text tab of the post editor, because of accessibility concerns for screen reader users and because Gutenberg was about to replace that editor anyway. And every user got a Syntax Highlighting option on their profile screen to switch CodeMirror off.

#Sandboxed PHP edits in the theme and plugin editors

The release post sums it up as avoiding “the dreaded white screen”. The mechanism, from Trac #21622, is a rollback. When you save a PHP file in the theme or plugin editor, WordPress keeps a copy of the old contents, writes your change, then makes a loopback request to the editor screen with your cookies. If that request hits a fatal error, the old file is restored. If not, a second loopback request checks the homepage. On any fatal error you get the message and keep your edit in the editor to fix it. If the loopback requests cannot complete, the edit is reverted and you are told to use SFTP.

Saves now happen over Ajax, and leaving the page with unsaved changes triggers an “Are you sure?” dialog. Before 4.9, the plugin editor tried to catch fatal errors by deactivating and reactivating the plugin, which could leave a critical plugin switched off, and themes had no protection at all.

The editors also changed around the edges. The first visit shows a warning that editing files directly is risky, and the theme editor points you to Additional CSS instead. More file types became editable (including js, json, scss, md, svg and yml), files deeper than two directories could be opened, and the file list became an expandable tree.

#Using the WordPress code editor in your own plugin

CodeMirror in 4.9 is also an API. The wp_enqueue_code_editor() function takes a file type, a file name or a codemirror settings array, picks sensible defaults for the language and returns the settings, or false when the user has turned syntax highlighting off. The dev note’s example turns the biography field on the profile screen into an HTML editor:

add_action( 'admin_enqueue_scripts', function() {
	if ( 'profile' !== get_current_screen()->id ) {
		return;
	}

	// Enqueue code editor and settings for manipulating HTML.
	$settings = wp_enqueue_code_editor( array( 'type' => 'text/html' ) );

	// Bail if user disabled CodeMirror.
	if ( false === $settings ) {
		return;
	}

	wp_add_inline_script(
		'code-editor',
		sprintf(
			'jQuery( function() { wp.codeEditor.initialize( "description", %s ); } );',
			wp_json_encode( $settings )
		)
	);
} );

Before the settings are returned they pass through the wp_code_editor_settings filter, which you can use to change options such as lineWrapping globally. Core registers the library under the wp-codemirror handle and exposes it as wp.CodeMirror instead of a global CodeMirror object, so it does not clash with plugins that ship their own copy. In the Customizer, the same editor is available as a control through WP_Customize_Code_Editor_Control.

#WordPress 4.9 widget changes

Adding photo galleries to the sidebar became native. The Gallery widget followed the image, audio and video widgets added in WordPress 4.8, and the documentation lists it as Trac #41914.

The Text widget changed too. It gained an Add Media button for images, video and audio, and it began running shortcodes. That request (Trac #10457) had been open for over eight years, and it meant plugins and themes no longer needed add_filter( 'widget_text', 'do_shortcode' ). Text widgets also accepted oEmbeds, so a YouTube URL dropped into the widget became an embedded player, and the Video widget learned to handle providers other than YouTube and Vimeo.

On the widgets admin screen, a new dirty state shows when a widget has been saved and asks “Are you sure?” if you try to leave with unsaved changes.

#Security, roles and developer changes in WordPress 4.9

#New capabilities and account security

The documentation page and the field guide list several changes that matter for anyone managing users:

  • singular activate_plugin and deactivate_plugin capabilities, checked against a specific plugin, so a role can be allowed to toggle some plugins and not others,
  • dedicated capabilities for installing and updating language files,
  • a confirmation link sent by email when a user tries to change their email address (Trac #16470),
  • more reliable role and capability initialisation when code switches between sites on multisite, plus a new get_site_by() function.

#Customizer JS API, MediaElement and removals

For developers, the Customizer JavaScript API lost many pain points listed in the field guide: default parameters for constructs, base control templates, a date/time control, and notifications at global, panel and section level. MediaElement.js was upgraded to 4.2.6, which according to the release post removes the jQuery dependency, improves accessibility and fixes many bugs.

Some things left core. SWFUpload was removed, and Press This moved out of core into a separate plugin. The REST API began requiring named URL parameters in route regular expressions, so numeric matches no longer work. The documentation also notes that core and its unit test suite were fully compatible with the upcoming PHP 7.2.

#From WordPress 4.9 to 5.0 and Gutenberg

#WordPress release timeline from 4.9 to 6.x

2017 (4.9):

  • Last version with the classic editor as default
  • Gutenberg in development as a plugin, with the release post asking for testers
  • CodeMirror kept out of the post editor because Gutenberg was replacing it

2018 (5.0):

  • Gutenberg introduced as the default editor
  • Classic Editor plugin available for sites that wanted the old screen

2019 to 2021:

  • Gutenberg matured release by release
  • Block patterns introduced
  • Full Site Editing in development

2022 onwards:

  • Block themes and the Site Editor in core
  • Classic themes and the Customizer still supported

#Classic Editor and Gutenberg after 4.9

Just a year after 4.9, WordPress 5.0 arrived with Gutenberg. The community split into two camps:

Traditionalists:

  • Stuck with the “Classic Editor” plugin
  • Continued using PHP-based themes
  • Preferred page builders (Elementor, Divi)
  • The Classic Editor plugin still has millions of installs

Modern creators:

  • Embraced the Full Site Editing (FSE) model
  • Everything, including header and footer, built with blocks
  • Adopted block themes
  • Shipped richer block patterns and templates

#Which WordPress 4.9 features still matter

#CodeMirror and Customizer drafts in WordPress today

CodeMirror:

  • Still used in the theme and plugin file editors and in Additional CSS
  • Still available to plugins through wp_enqueue_code_editor()

Customizer drafts:

  • Still available on classic themes that use the Customizer
  • Scheduling still depends on WP-Cron, so the cron advice from 2017 still applies
  • Block themes use the Site Editor instead, which has its own revisions and preview

File editor safety:

  • The loopback rollback from 4.9 is still why a broken PHP edit in the dashboard usually does not take the site down
  • The DISALLOW_FILE_EDIT constant in wp-config.php still turns the file editors off entirely on production

#WordPress 4.9 vs WordPress 6.x

#How theme development changed since WordPress 4.9

Theme development:

  • 4.9: PHP templates, functions.php, hooks
  • 6.x: Block themes, theme.json, Site Editor

Content editing:

  • 4.9: Classic editor, shortcodes, widgets
  • 6.x: Gutenberg blocks, patterns, templates

Customization:

  • 4.9: Customizer, theme options
  • 6.x: Site Editor, block settings

Developer tools:

  • 4.9: CodeMirror, WP_DEBUG
  • 6.x: Block development tools such as @wordpress/scripts

#Features replaced and added since WordPress 4.9

Replaced or optional:

  • Classic editor (optional plugin)
  • Many Customizer features (replaced by the Site Editor in block themes)
  • Widget screens (block-based widget areas)

Still there:

  • CodeMirror in code fields
  • Sandboxed PHP edits in the file editors

New:

  • Block editor
  • Full Site Editing
  • Block patterns
  • theme.json
  • React-based editor development

#What developers can learn from WordPress 4.9

#1. Infrastructure first, interface later

Changesets shipped in 4.7 with no interface, and 4.9 added drafts, scheduling and locking on top. Splitting storage from UI let two releases deliver the feature without breaking existing sites.

#2. Backward compatibility in WordPress

WordPress maintained backward compatibility even through major changes. The Classic Editor plugin kept old sites working after 5.0, and the shortcode support in the Text widget removed a filter that themes and plugins had been adding by hand.

#3. Safety nets for people who edit in production

The loopback rollback, linting that blocks saving and the warning on the file editors all assume people will edit live sites. Planning for that turned out more useful than pretending they would not.

#WordPress 4.9 summary and key achievements

WordPress 4.9 “Tipton” was the last version of “classic” WordPress before the Gutenberg editor.

Key achievements:

  • Customizer drafts, scheduling, locking and preview links
  • CodeMirror with linting in Additional CSS, the Custom HTML widget and the file editors
  • Sandboxed PHP edits that roll back fatal errors
  • Gallery widget, shortcodes and media in the Text widget
  • New capabilities and email change confirmation

For developers:

  • Read the 4.9 field guide when you maintain a classic theme, since much of the Customizer and code editor API you touch dates from it
  • Use wp_enqueue_code_editor() instead of bundling your own CodeMirror
  • Set up a real cron if you rely on scheduled changesets
Next step

Turn the article into an actual implementation

This block strengthens internal linking and gives readers the most relevant next move instead of leaving them at a dead end.

Want this implemented on your site?

If you want to convert the article into a working site improvement, redesign, or build plan, I can define the scope and implement it.

Related cluster

Explore other WordPress services and knowledge base

Strengthen your business with professional technical support in key areas of the WordPress ecosystem.

Frequently asked questions

Practical answers to apply the topic in real execution.

Why is WordPress 4.9 still worth understanding?#
It was the last major classic-era release before Gutenberg, so it helps explain how WordPress moved from Customizer- and PHP-led workflows toward the block era.
What was the most practical improvement in WordPress 4.9?#
For many developers and site owners, the Customizer draft and scheduling flow was one of the biggest practical improvements because it made design changes safer to review before publishing.
Did WordPress 4.9 already include Gutenberg?#
No. The 4.9 release post invited people to test Gutenberg as a plugin and contribute on GitHub, but the block editor shipped later with WordPress 5.0.

Need an FAQ tailored to your industry and market? We can build one aligned with your business goals.

Let’s discuss

Related Articles