Twenty Twenty-Five

Welcome to the development repository for the default theme that will launch with WordPress 6.7.

About

While ideating Twenty Twenty-Five, one recurring idea was that simple things should be intuitive while complex things should be possible. This concept of simplicity and complexity leads to a reliable foundation for extending a default WordPress experience to make it yours.

Twenty Twenty-Five embodies ultimate flexibility and adaptability, showcasing the many ways WordPress enables people to tell their stories with many patterns and styles to choose from. The glimpses of natural beauty and ancestry woven into the theme evoke ideas of impermanence, the passage of time, and continuous evolution.

Introducing Twenty Twenty-Five

Twenty Twenty-Five is built as a block theme. The theme aims to ship with as little CSS as possible: our goal is for all theme styles to be configured through theme.json and editable through Global Styles. The theme development team will work closely with Gutenberg contributors to build design tools in the block editor that enable this goal.

If you'd like to see the latest and greatest version of Twenty Twenty-Five, there is a demo site that is automatically updated every five minutes with the newest commits to this repo.

Contributing

Connect your GitHub account to your WordPress.org account to receive props for your contributions. Please see the tutorials on Linking your GitHub and w.org profiles.

If you would like to contribute code, the list of open issues is a great place to start looking for tasks. Pull requests are preferred when linked to an existing issue.

Contributing is not just for developers! There are many opportunities to help with testing, triage, discussion, design, building patterns and templates, and more. Please look through open issues, and join in wherever you feel most comfortable.

If you'd like to help with triage, open a new issue and one of the maintainers will help you get set up with the ability to add labels to issues and PRs.

Getting Started

To get started with development:

  1. Set up a WordPress instance, we recommend wp-env or Local as an alternative to Docker. Alternatively you can use WordPress Playground to test the theme directly in the browser.
  2. Install the Gutenberg plugin
  3. Clone / download this repository into your /wp-content/themes/ directory.

Also, consider enabling development mode with define( 'WP_DEVELOPMENT_MODE', 'theme' ); in your wp-config.php. This will help minimize caching of theme.json while you're developing.

To enable development mode using WP CLI use the following command in your terminal inside your installation directory wp config set 'WP_DEVELOPMENT_MODE' theme.

Pattern creation guidelines

Reference guide for patterns in the handbook. A few things to have in mind when building patterns for the default theme:

  • Category selection

When creating WordPress block patterns, it's important to carefully choose the appropriate category for your pattern. WordPress provides a set of default categories, each serving a specific purpose. Let's stick to using the default categories. We can add multiple of them separating them by commas. The list of the slug is here.

  • Hiding patterns from the inserter

You can control the visibility of your block pattern in the inserter by adding the following line of code when registering the pattern:

We do this for patterns we don't want the user to access via the inserter or the pattern library. This is usually the case for utility patterns that we create for translation purposes such as the 404 pattern.

We do this by adding the following line:

* Inserter: no

Let's prefix hidden patterns using hidden- when we name the pattern file.

  • Different translation functions and when to use them

WordPress block patterns should be internationalized to make them accessible to a global audience.

esc_html_x(): Employ this function when you need to translate and escape text for display within HTML. It's useful for multilingual websites as it provides translation support while also ensuring HTML safety.

esc_html__(): Similar to esc_html_x(), use this function for translating and escaping HTML-embedded text. It's a simpler version when context-specific translations are not needed.

esc_attr__() and esc_attr_x(): Use this function to escape and sanitize text meant for HTML attributes, such as image source URLs or link targets. It helps prevent security vulnerabilities by ensuring that user inputs are safe for use in attributes.

esc_html_e: works just like esc_html__() but you don't need to use echo to output the string

When we have simple HTML tags in our translatable strings we would use echo wp_kses_post( __( 'Lorem ipsum <em>Hello</em> dolor sit amet.', 'textdomain' ) );. This syntax is clearer for translators than using sprintf() and it allows them to remove the markup if it doesn't work on their own language.

These functions enhance security and support localization efforts in WordPress block patterns, ensuring that text is safe and can be easily translated.

  • Patterns with images

You can find the images used in the theme designs, in this folder.

To create dynamic image links in your block patterns, utilize the get_template_directory_uri() function. This function retrieves the URL of the current theme's directory, ensuring that the image links are relative to the theme and work correctly even if the website's directory structure changes or if we are using a child theme. This is essential for maintaining the stability and portability of your patterns.

Make sure to add alt text to your images and to make sure to remove the IDs from them. An example would be:

<!-- wp:image {"id":125,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="http://wp-stable.test/wp-content/themes/twentytwentyfive/assets/images/project.webp" alt="" class="wp-image-125"/></figure>
<!-- /wp:image -->

would turn into

<!-- wp:image {"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="<?php echo esc_url( get_template_directory_uri() ); ?>/assets/images/project.webp" alt="<?php echo esc_attr_x( 'Picture of a building', 'Alt text for project picture', 'twentytwentyfive' ); ?>"/></figure>
<!-- /wp:image -->
  • Image license attribution

When adding images to the theme, we need to add the license attribution to the readme.txt file. For Twenty Twenty-Five almost all images come from rawpixel.com, and we have stored them in this folder.

The filename of each image includes the ID, and the way to get the license is by following the link rawpixel.com/image/$id. Let's take the following filename as an example:

image-from-rawpixel-id-2211732-jpeg.webp

For that particular image, the id would be 2211732. And the link you should follow to get the license would be rawpixel.com/image/2211732.

So, in order to find and add the license, what you need to do is the following:

  • Get the image from the shared Google Drive folder.

  • Look for the id in the filename.

  • Visit rawpixel.com/image/$id, replacing $id with the value you get from the filename.

  • Get the license from the image page.

  • Put it in the readme.txt file.

  • Use of Post Types, Block Types and Template Types

We use Block Types when the pattern uses custom markup for a specific block or one of the default template parts (footer and header). Using this will suggest the pattern when someone inserts said block or template part. This is commonly used for query, post-content block, template or footer.

Template Types is used when we want our pattern as a suggestion for a specific template. In this case we provide the template slug (404, home, single...)

Post Types is used to restrict the post type we want the pattern to be used for. commonly used for full page patterns.

  • Spacing, colors and font sizes

Using presets for spacing, font sizes, and colors in WordPress block patterns is preferred over hardcoded values for three key reasons:

Consistency: Presets ensure a uniform design across the theme, promoting a cohesive visual identity.

Scalability: They make global design changes easier during development, saving time and effort.

Accessibility: Presets facilitate adherence to accessibility standards, making your patterns more usable and readable for a wider audience.

  • Other tips

In the same way we remove IDs from image blocks, we need to remove queryId from query blocks too. Also, if any of our template parts have a theme attribute, that needs to remove too.

<!-- wp:query {"queryId":18,"query":{"perPage":8,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true}} -->

turns into

<!-- wp:query {"query":{"perPage":8,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true}} -->

and

<!-- wp:template-part {"slug":"header-portfolio","theme":"twentytwentyfive","area":"header","tagName":"header"} /-->

turns into

<!-- wp:template-part {"slug":"header-portfolio","area":"header","tagName":"header"} /-->

If we are constantly assigning properties to the same block over and over again (ie: border radius to images), consider moving those properties to the theme.json.

When building full page patterns, let's prefix them by using page-

One way to control the order in which patterns are displayed in the inserter is by changing the name of the file (they are sorted alphabetically)

Tips for Contributors

  • As stated above, a goal for the theme is to have as little CSS as possible. Much of the theme's visual treatments should be handled by the Block Editor and Global Styles. As a general rule, if multiple themes would benefit from the CSS you're considering adding, it might reasonably be provided by Gutenberg instead. Let's include clear code comments for any CSS we do include.
  • Similarly, let's refrain from building any custom-built PHP or JavaScript-based workarounds for functionality that might reasonably be provided by the Block Editor, let's keep the code simple to help with future maintenance.
  • In accordance to those last two bullets, this theme has no required build process.
  • Refrain from creating pull requests for translatable strings until all patterns, parts, and templates are completed.

Discussions

On Wednesdays at 15:00 UTC, there are weekly Slack meetings in the #core-themes channel in Make WordPress Slack (registration required) to coordinate development of the theme. Agenda notes will be posted before meetings and summaries posted after the meeting.

Requirements

  • Gutenberg plugin (latest)
  • WordPress 6.6+ (Will be 6.7 at the time of release)
  • PHP 7.2.24+
  • License: GPLv2 or later

Some theme features / PRs may require the development version of Gutenberg and will be described or tagged accordingly.

Testing

To run the tests locally, you'll need:

  • Node.js: It's recommended to install Node.js using nvm, which helps manage the Node.js version required by the project. Installation instructions here.
  • Composer: you can find the instructions for your OS here.

Once you have these tools set up, install the necessary development dependencies by running:

npm i && composer install

You can then use the following commands to test the code:

  • npm run lint:css: Lints all CSS files.
  • npm run lint:css:fix: Lints and attempts to autofix any issues in the CSS files.
  • npm run lint:php: Checks PHP files for syntax and standards errors according to WordPress coding standards.
  • npm run lint:php:fix: Attempts to automatically fix PHP errors.

Resources

Timeline

The theme will be released with WordPress 6.7 and follow the key dates / milestones associated with its future development schedule.