diff --git a/docs/getting-started/create-block/README.md b/docs/getting-started/create-block/README.md deleted file mode 100644 index 22a28560c76a81..00000000000000 --- a/docs/getting-started/create-block/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Create a Block Tutorial - -Let's get you started creating your first block for the WordPress Block Editor. We will create a simple block that allows the user to type a message and style it. - -The tutorial includes setting up your development environment, tools, and getting comfortable with the new development model. If you are already comfortable, try the quick start below, otherwise step through whatever part of the tutorial you need. - -## Prerequisites - -The first thing you need is a development environment and tools. This includes setting up your WordPress environment, Node, NPM, and your code editor. If you need help, see the [setting up your development environment documentation](/docs/getting-started/devenv/README.md). - -## Table of Contents - -The create a block tutorials breaks down to the following sections. - -1. [WordPress Plugin](/docs/getting-started/create-block/wp-plugin.md) -2. [Anatomy of a Gutenberg Block ](/docs/getting-started/create-block/block-anatomy.md) -3. [Block Attributes](/docs/getting-started/create-block/attributes.md) -4. [Code Implementation](/docs/getting-started/create-block/block-code.md) -5. [Authoring Experience](/docs/getting-started/create-block/author-experience.md) -6. [Finishing Touches](/docs/getting-started/create-block/finishing.md) -7. [Share your Block with the World](/docs/getting-started/create-block/submitting-to-block-directory.md) diff --git a/docs/getting-started/create-block/attributes.md b/docs/getting-started/create-block/attributes.md deleted file mode 100644 index 02a55f380dcee1..00000000000000 --- a/docs/getting-started/create-block/attributes.md +++ /dev/null @@ -1,87 +0,0 @@ -# Block Attributes - -Attributes are the way a block stores data, they define how a block is parsed to extract data from the saved content. - -For this block tutorial, we want to allow the user to type in a message that we will display stylized in the published post. So, we need to add a **message** attribute that will hold the user message. The following code defines a **message** attribute; the attribute type is a string; the source is the text from the selector which is a `div` tag. - -```json -"attributes": { - "message": { - "type": "string", - "source": "text", - "selector": "div", - "default": "" - } -}, -``` - -Add this to the `src/block.json` file. The `attributes` are at the same level as the _name_ and _title_ fields. - -When the block loads it will look at the saved content for the block, look for the div tag, take the text portion, and store the content in an `attributes.message` variable. - -Note: The text portion is equivalent to `innerText` attribute of a DOM element. For more details and other examples see the [Block Attributes documentation](/docs/reference-guides/block-api/block-attributes.md). - -## Edit and Save - -The **attributes** are passed to both the `edit` and `save` functions. The **setAttributes** function is also passed, but only to the `edit` function. The **setAttributes** function is used to set the values. Additional parameters are also passed in to the `edit` and `save` functions, see [the edit/save documentation](/docs/reference-guides/block-api/block-edit-save.md) for more details. - -The `attributes` is a JavaScript object containing the values of each attribute, or default values if defined. The `setAttributes` is a function to update an attribute. - -```js -export default function Edit( { attributes, setAttributes } ) { - // ... -} -``` - -## TextControl Component - -For our example block, the component we are going to use is the **TextControl** component, it is similar to an HTML text input field. You can see [documentation for TextControl component](/packages/components/src/text-control/README.md). You can browse an [interactive set of components in this Storybook](https://wordpress.github.io/gutenberg/). - -The component is added similar to an HTML tag, setting a label, the `value` is set to the `attributes.message` and the `onChange` function uses the `setAttributes` to update the message attribute value. - -The save function will simply write the `attributes.message` as a div tag since that is how we defined it to be parsed. - -OPTIONAL: For IDE support (code completion and hints), you can install the `@wordpress/components` module which is where the TextControl component is imported from. This install command is optional since the build process automatically detects `@wordpress/*` imports and specifies as dependencies in the assets file. - -```shell -npm install @wordpress/components --save -``` - -Update the edit.js and save.js files to the following, replacing the existing functions. - -**edit.js** file: - -```js -import { __ } from '@wordpress/i18n'; -import { useBlockProps } from '@wordpress/block-editor'; -import { TextControl } from '@wordpress/components'; -import './editor.scss'; - -export default function Edit( { attributes, setAttributes } ) { - return ( -
No Message.
-wp-env
to create a local WordPress development environment. However, feel free to use alternate local development tools if you already have one that you prefer.
+wp-env
, instead, navigate to the plugins/
folder in your local WordPress installation using the terminal and run the following command.
+--variant=dynamic
flag. This tells create-block
you want to scaffold a dynamically rendered block. Later in this tutorial, you will learn about dynamic and static rendering and add static rendering to this block.
+save.js
file. Later in the tutorial, you will add this file to the plugin to enable static rendering, so stay tuned.
+viewBox
parameter above.
++ { __( + 'Copyright Date Block – hello from the editor!', + 'copyright-date-block-demo' + ) } +
+ ); +} +``` + +It looks a bit more complicated than it is. + +- [`useBlockProps()`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#block-wrapper-props) outputs all the necessary CSS classes and styles in the [block's wrapper](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-wrapper/#the-edit-components-markup) needed by the Editor, which includes the style provided by the block supports you added earlier +- [`__()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/) is used for the internationalization of text strings + +© { currentYear }
+ ); +} +``` + +Save the `edit.js` file and refresh the Editor. You will now see the copyright symbol (©) followed by the current year. + +![The block in the Editor displays the correct content](https://developer.wordpress.org/files/2023/12/block-tutorial-8.png) + +### Updating render.php + +While the block is working properly in the Editor, the default block message is still being displayed on the front end. To fix this, open the [`render.php`](https://developer.wordpress.org/block-editor/getting-started/fundamentals/file-structure-of-a-block/#render-php) file, and you will see the following. + +```php + +> + +
+ +``` + +Similar to the `useBlockProps()` function in the Editor, [`get_block_wrapper_attributes()`](https://developer.wordpress.org/reference/functions/get_block_wrapper_attributes/) outputs all the necessary CSS classes and styles in the [block's wrapper](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-wrapper/#the-server-side-render-markup). Only the content needs to be updated. + +You can use `date( "Y" )` to get the current year in PHP, and your `render.php` should look like this. + +```php + +>©
+``` + +Save the file and confirm that the block appears correctly in the Editor and on the front end. + +### Cleaning up + +When you use the `create-block` package to scaffold a block, it might include files that you don't need. In the case of this tutorial, the block doesn't use stylesheets or font end JavaScipt. Clean up the plugin's `src/` folder with the following actions. + +1. In the `edit.js` file, remove the lines that import `editor.scss` +2. In the `index.js` file, remove the lines that import `style.scss` +3. Delete the editor.scss, style.scss, and view.js files + +Finally, make sure that there are no unsaved changes and then terminate the `npm run start` command. Run `npm run build` to optimize your code and make it production-ready. + +You have built a fully functional WordPress block, but let's not stop here. In the next sections, we'll add functionality and enable static rendering. + +## Adding block attributes + +The Copyright Date Block you have built shows the current year, but what if you wanted to display a starting year as well? + +![What you're going to build](https://developer.wordpress.org/files/2023/12/block-tutorial-1.png) + +This functionality would require users to enter their starting year somewhere on the block. They should also have the ability to toggle it on or off. + +You could implement this in different ways, but all would require [block attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/). Attributes allow you to store custom data for the block that can then be used to modify the block's markup. + +To enable this starting year functionality, you will need one attribute to store the starting year and another that will be used to tell WordPress whether the starting year should be displayed or not. + +### Updating block.json + +Block attributes are generally specified in the [`block.json`](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#data-storage-in-the-block-with-attributes) file. So open up the file and add the following section after the `example` in line 9. + +```json +"attributes": { + "showStartingYear": { + "type": "boolean" + }, + "startingYear": { + "type": "string" + } +}, +``` + +You must indicate the `type` when defining attributes. In this case, the `showStartingYear` should be true or false, so it's set to `boolean`. The `startingYear` is just a string. + +Save the file, and you can now move on to the Editor. + +### Updating edit.js + +Open the `edit.js` file. You will need to accomplish two tasks. + +Add a user interface that allows the user to enter a starting year, toggle the functionality on or off, and store these settings as attributes +Update the block to display the correct content depending on the defined attributes + +#### Adding the user interface + +Earlier in this tutorial, you added block supports that automatically created Color and Typography panels in the Settings Sidebar of the block. You can create your own custom panels using the `InspectorControls` component. + +##### Inspector controls + +The `InspectorControls` belongs to the [`@wordpress/block-editor`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/) package, so you can import it into the `edit.js` file by adding the component name on line 14. The result should look like this. + +```js +import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; +``` + +Next, update the Edit function to return the current block content and an `InspectorControls` component that includes the text "Testing." You can wrap everything in a [Fragment](https://react.dev/reference/react/Fragment) (`<>>`) to ensure proper JSX syntax. The result should look like this. + +```js +export default function Edit() { +const currentYear = new Date().getFullYear().toString(); + + return ( + <> +© { currentYear }
+ > + ); +} +``` +Save the file and refresh the Editor. When selecting the block, you should see the "Testing" message in the Settings Sidebar. + +![The Setting Sidebar now displays the message](https://developer.wordpress.org/files/2023/12/block-tutorial-9.png) + +##### Components and panels + +Now, let's use a few more Core components to add a custom panel and the user interface for the starting year functionality. You will want to import [`PanelBody`](https://developer.wordpress.org/block-editor/reference-guides/components/panel/#panelbody), [`TextControl`](https://developer.wordpress.org/block-editor/reference-guides/components/text-control/), and [`ToggleControl`](https://developer.wordpress.org/block-editor/reference-guides/components/toggle-control/) from the [`@wordpress/components`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-components/) package. + +Add the following line below the other imports in the `edit.js` file. + +```js +import { PanelBody, TextControl, ToggleControl } from '@wordpress/components'; +``` + +Then wrap the "Testing" message in the `PanelBody` component and set the `title` parameter to "Settings". Refer to the [component documentation](https://developer.wordpress.org/block-editor/reference-guides/components/panel/#panelbody) for additional parameter options. + +```js +export default function Edit() { +const currentYear = new Date().getFullYear().toString(); + + return ( + <> +© { currentYear }
+ > + ); +} +``` + +Save the file and refresh the Editor. You should now see the new Settings panel. + +![The Setting Sidebar now displays a custom panel](https://developer.wordpress.org/files/2023/12/block-tutorial-10.png) + +##### Text control + +The next step is to replace the "Testing" message with a `TextControl` component that allows the user to set the `startingYear` attribute. However, you must include two parameters in the `Edit()` function before doing so. + +- `attributes` is an object that contains all the attributes for the block +- `setAttributes` is a function that allows you to update the value of an attribute + +With these parameters included, you can fetch the `showStartingYear` and `startingYear` attributes. + +Update the top of the `Edit()` function to look like this. + +```js +export default function Edit( { attributes, setAttributes } ) { + const { showStartingYear, startingYear } = attributes; + ... +``` + +console.log( attributes );
at the top of the Edit()
function. This can be useful when building and testing a custom block.
+© { currentYear }
+ > + ); +} +``` + +Save the file and refresh the Editor. Confirm that a text field now exists in the Settings panel. Add a starting year and confirm that when you update the page, the value is saved. + +![A live look at editing the new Starting Year field in the Settings Sidebar](https://developer.wordpress.org/files/2023/12/block-tutorial-11.gif) + +##### Toggle control + +Next, let's add a toggle that will turn the starting year functionality on or off. You can do this with a `ToggleControl` component that sets the `showStartingYear` attribute. It should include: + +1. A `label` property set to "Show starting year" +2. A `checked` property set to the attribute `showStartingYear` +3. An `onChange` property that updates the `showStartingYear` attribute whenever the toggle is checked or unchecked + +You can also update the "Starting year" text input so it's only displayed when `showStartingYear` is `true`, which can be done using the `&&` logical operator. + +The `Edit()` function should look like the following. + +```js +export default function Edit( { attributes, setAttributes } ) { + const { showStartingYear, startingYear } = attributes; + const currentYear = new Date().getFullYear().toString(); + + return ( + <> +© { currentYear }
+ > + ); +} +``` + +Save the file and refresh the Editor. Confirm that clicking the toggle displays the text input, and when you update the page, the toggle remains active. + +![A live look at editing the new Show Starting Year toggle in the Settings Sidebar](https://developer.wordpress.org/files/2023/12/block-tutorial-12.gif) + +#### Updating the block content + +So far, you have created the user interface for adding a starting year and updating the associated block attributes. Now you need to actually update the block content in the Editor. + +Let's create a new variable called `displayDate`. When `showStartingYear` is `true` and the user has provided a `startingYear`, the `displayDate` should include the `startingYear` and the `currentYear` separated by an em dash. Otherwise, just display the `currentYear`. + +The code should look something like this. + +```js +let displayDate; + +if ( showStartingYear && startingYear ) { + displayDate = startingYear + '–' + currentYear; +} else { + displayDate = currentYear; +} +``` + +let
, it means that the variable may be reassigned later. Declaring a variable with const
means that the variable will never change. You could rewrite this code using const
. It's just a matter of personal preference.
+© { displayDate }
+ > + ); +} +``` + +Save the file and refresh the Editor. Confirm that the block content updates correctly when you make changes in the Settings panel. + +![A live look at the block content being updated by the new fields in the Setting Sidebar](https://developer.wordpress.org/files/2023/12/block-tutorial-13.gif) + +### Updating render.php + +While the Editor looks great, the starting year functionality has yet to be added to the front end. Let's fix that by updating the `render.php` file. + +Start by adding a variable called `$display_date` and replicate what you did in the `Edit()` function above. + +This variable should display the value of the `startingYear` attribute and the `$current_year` variable separated by an em dash, or just the `$current_year` is the `showStartingYear` attribute is `false`. + +Three variables are exposed in the render.php
, which you can use to customize the block's output:
$attributes
(array): The block attributes.$content
(string): The block default content.$block
(WP_Block): The block instance.> + © +
+``` + +Save the file and confirm that the correct block content is now appearing on the front end of your site. + +You have now successfully built a dynamically rendered custom block that utilizes block supports, core WordPress components, and custom attributes. In many situations, this is as far as you would need to go for a block displaying the copyright date with some additional functionality. + +In the next section, however, you will add static rendering to the block. This exercise will illustrate how block data is stored in WordPress and provide a fallback should this plugin ever be inadvertently disabled. + +## Adding static rendering + +A block can be dynamically rendered, statically rendered, or both. The block you have built so far is dynamically rendered. The HTML output of the block is not actually stored in the database, only the block markup and the associated attributes. + +You will see the following if you switch to the Code editor from within the Editor. + +```html + +``` + +Compare this to a statically rendered block like the Paragraph block. + +```html + +This is a test.
+ +``` + +The HTML of the paragraph is stored in post content and saved in the database. + +You can learn more about dynamic and static rendering in the [Fundamentals documentation](https://developer.wordpress.org/block-editor/getting-started/fundamentals/). While most blocks are either dynamically or statically rendered, you can build a block that utilizes both methods. + +### Why add static rendering? + +When you add static rendering to a dynamically rendered block, the `render.php` file will still control the output on the front end, but the block's HTML content will be saved in the database. This means that the content will remain if the plugin is ever removed from the site. In the case of this Copyright Date Block, the content will revert to a Custom HTML block that you can easily convert to a Paragraph block. + +![An error message in the Editor when a block type no longer exists](https://developer.wordpress.org/files/2023/12/block-tutorial-14.png) + +While not necessary in all situations, adding static rendering to a dynamically rendered block can provide a helpful fallback should the plugin ever be disabled unintentionally. + +Also, consider a situation where the block markup is included in a block pattern or theme template. If a user installs that theme or uses the pattern without the Copyright Date Block installed, they will get a notice that the block is not available, but the content will still be displayed. + +Adding static rendering is also a good exploration of how block content is stored and rendered in WordPress. + +### Adding a save function + +Start by adding a new file named `save.js` to the `src/` folder. In this file, add the following. + +```js +import { useBlockProps } from '@wordpress/block-editor'; + +export default function save() { + return ( ++ { 'Copyright Date Block – hello from the saved content!' } +
+ ); +} +``` + +This should look similar to the original `edit.js` file, and you can refer to the [block wrapper](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-wrapper/#the-save-components-markup) documentation for additional information. + +Next, in the `index.js` file, import this `save()` function and add a save property to the `registerBlockType()` function. Here's a simplified view of the updated file. + +```js +import save from './save'; + +... + +registerBlockType( metadata.name, { + icon: calendarIcon, + edit: Edit, + save +} ); +``` + +save
instead of save: save
.
+Copyright Date Block – hello from the saved content!
+ +``` + +You will often encounter block validation errors when building a block with static rendering, and that's ok. The output of the `save()` function must match the HTML in the post content exactly, which may end up out of sync as you add functionality. So long as there are no validation errors when you're completely finished building the block, you will be all set. + +### Updating save.js + +Next, let's update the output of the `save()` function to display the correct content. Start by copying the same approach used in `edit.js`. + +1. Add the `attributes` parameter to the function +2. Define the `showStartingYear` and `startingYear` variables +3. Define a `currentYear` variable +4. Define a `displayDate` variable depending on the values of `currentYear`, `showStartingYear`, and `startingYear` + +The result should look like this. + +```js +export default function save( { attributes } ) { + const { showStartingYear, startingYear } = attributes; + const currentYear = new Date().getFullYear().toString(); + + let displayDate; + + if ( showStartingYear && startingYear ) { + displayDate = startingYear + '–' + currentYear; + } else { + displayDate = currentYear; + } + + return ( +© { displayDate }
+ ); +} +``` + +Save the file and refresh the Editor. Click "Attempt Block Recovery" and update the page. Check the Code editor, and the block markup should now look something like this. + +```html + +© 2017–2023
+ +``` + +At this point, it might look like you're done. The block content is now saved as HTML in the database and the output on the front end is dynamically rendered. However, there are still a few things that need to be addressed. + +Consider the situation where the user added the block to a page in 2023 and then went back to edit the page in 2024. The front end will update as expected, but in the Editor, there will be a block validation error. The `save()` function knows that it's 2024, but the block content saved in the database still says 2023. + +Let's fix this in the next section. + +### Handling dynamic content in statically rendered blocks + +Generally, you want to avoid dynamic content in statically rendered blocks. This is part of the reason why the term "dynamic" is used when referring to dynamic rendering. + +That said, in this tutorial, you are combining both rendering methods, and you just need a bit more code to avoid any block validation errors when the year changes. + +The root of the issue is that the `currentYear` variable is set dynamically in the `save()` function. Instead, this should be a static variable within the function, which can be solved with an additional attribute. + +#### Adding a new attribute + +Open the `block.json` file and add a new attribute called `fallbackCurrentYear` with the type `string`. The `attributes` section of the file should now look like this. + +```json +"attributes": { + "fallbackCurrentYear": { + "type": "string" + }, + "showStartingYear": { + "type": "boolean" + }, + "startingYear": { + "type": "string" + } +}, +``` + +Next, open the `save.js` file and use the new `fallbackCurrentYear` attribute in place of `currentYear`. Your updated `save()` function should look like this. + +```js +export default function save( { attributes } ) { + const { fallbackCurrentYear, showStartingYear, startingYear } = attributes; + + let displayDate; + + if ( showStartingYear && startingYear ) { + displayDate = startingYear + '–' + fallbackCurrentYear; + } else { + displayDate = fallbackCurrentYear; + } + + return ( +© { displayDate }
+ ); +} +``` + +Now, what happens if the `fallbackCurrentYear` is undefined? + +Before the `currentYear` was defined within the function, so the `save()` function always had content to return, even if `showStartingYear` and `startingYear` were undefined. + +Instead of returning just the copyright symbol, let's add a condition that if `fallbackCurrentYear` is not set, return `null`. It's generally better to save no HTML in the database than incomplete data. + +The final `save()` function should look like this. + +```js +export default function save( { attributes } ) { + const { fallbackCurrentYear, showStartingYear, startingYear } = attributes; + + if ( ! fallbackCurrentYear ) { + return null; + } + + let displayDate; + + if ( showStartingYear && startingYear ) { + displayDate = startingYear + '–' + fallbackCurrentYear; + } else { + displayDate = fallbackCurrentYear; + } + + return ( +© { displayDate }
+ ); +} +``` + +Save both the `block.json` and `save.js` files; you won't need to make any more changes. + +#### Setting the attribute in edit.js + +The `save()` function now uses the new `fallbackCurrentYear`, so it needs to be set somewhere. Let's use the `Edit()` function. + +Open the `edit.js` file and start by defining the `fallbackCurrentYear` variable at the top of the `Edit()` functional alongside the other attributes. Next, review what's happening in the function. + +When the block loads in the Editor, the `currentYear` variable is defined. The function then uses this variable to set the content of the block. + +Now, let's set the `fallbackCurrentYear` attribute to the `currentYear` when the block loads if the attribute is not already set. + +```js +if ( currentYear !== fallbackCurrentYear ) { + setAttributes( { fallbackCurrentYear: currentYear } ); +} +``` + +This will work but can be improved by ensuring this code only runs once when the block is initialized. To do so, you can use the [`useEffect`](https://react.dev/reference/react/useEffect) React hook. Refer to the React documentation for more information about how to use this hook. + +First, import `useEffect` with the following code. + +```js +import { useEffect } from 'react'; +``` + +Then wrap the `setAttribute()` code above in a `useEffect` and place this code after the `currentYear` definition in the `Edit()` function. The result should look like this. + +```js +export default function Edit( { attributes, setAttributes } ) { + const { fallbackCurrentYear, showStartingYear, startingYear } = attributes; + + // Get the current year and make sure it's a string. + const currentYear = new Date().getFullYear().toString(); + + // When the block loads, set the fallbackCurrentYear attribute to the + // current year if it's not already set. + useEffect( () => { + if ( currentYear !== fallbackCurrentYear ) { + setAttributes( { fallbackCurrentYear: currentYear } ); + } + }, [ currentYear, fallbackCurrentYear, setAttributes ] ); + + ... +``` + +When the block is initialized in the Editor, the `fallbackCurrentYear` attribute will be immediately set. This value will then be available to the `save()` function, and the correct block content will be displayed without block validation errors. + +The one caveat is when the year changes. If a Copyright Date Block was added to a page in 2023 and then edited in 2024, the `fallbackCurrentYear` attribute will no longer equal the `currentYear`, and the attribute will be automatically updated to `2024`. This will update the HTML returned by the `save()` function. + +You will not get any block validation errors, but the Editor will detect that changes have been made to the page and prompt you to update. + +#### Optimizing render.php + +The final step is to optimize the `render.php` file. If the `currentYear` and the `fallbackCurrentYear` attribute are the same, then there is no need to dynamically create the block content. It is already saved in the database and is available in the `render.php` file via the `$block_content` variable. + +Therefore, update the file to render the `$block_content` if `currentYear` and `fallbackCurrentYear` match. + +```php +$current_year = date( "Y" ); + +// Determine which content to display. +if ( isset( $attributes['fallbackCurrentYear'] ) && $attributes['fallbackCurrentYear'] === $current_year ) { + + // The current year is the same as the fallback, so use the block content saved in the database (by the save.js function). + $block_content = $content; +} else { + + // The current year is different from the fallback, so render the updated block content. + if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) { + $display_date = $attributes['startingYear'] . '–' . $current_year; + } else { + $display_date = $current_year; + } + + $block_content = '© ' . esc_html( $display_date ) . '
'; +} + +echo wp_kses_post( $block_content ); +``` + +That's it! You now have a block that utilizes both dynamic and static rendering. + +## Wrapping up + +Congratulations on completing this tutorial and building your very own Copyright Date Block. Throughout this journey, you have gained a solid foundation in WordPress block development and are now ready to start building your own blocks. + +For final reference, the complete code for this tutorial is available in the [Block Development Examples](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/copyright-date-block-09aac3) repository on GitHub. + +Now, whether you're now looking to refine your skills, tackle more advanced projects, or stay updated with the latest WordPress trends, the following resources will help you improve your block development skills: + +- [Block Development Environment](https://developer.wordpress.org/block-editor/getting-started/devenv/) +- [Fundamentals of Block Development](https://developer.wordpress.org/block-editor/getting-started/fundamentals/) +- [WordPress Developer Blog](https://developer.wordpress.org/news/) +- [Block Development Examples](https://github.com/WordPress/block-development-examples) | GitHub repository + +Remember, every expert was once a beginner. Keep learning, experimenting, and, most importantly, have fun building with WordPress. diff --git a/docs/manifest.json b/docs/manifest.json index b91732962e0a91..6b5ee58d4d6a50 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -48,53 +48,11 @@ "parent": "getting-started" }, { - "title": "Create a Block Tutorial", - "slug": "create-block", - "markdown_source": "../docs/getting-started/create-block/README.md", + "title": "Tutorial: Build your first block", + "slug": "tutorial", + "markdown_source": "../docs/getting-started/tutorial.md", "parent": "getting-started" }, - { - "title": "WordPress Plugin", - "slug": "wp-plugin", - "markdown_source": "../docs/getting-started/create-block/wp-plugin.md", - "parent": "create-block" - }, - { - "title": "Anatomy of a Block", - "slug": "block-anatomy", - "markdown_source": "../docs/getting-started/create-block/block-anatomy.md", - "parent": "create-block" - }, - { - "title": "Block Attributes", - "slug": "attributes", - "markdown_source": "../docs/getting-started/create-block/attributes.md", - "parent": "create-block" - }, - { - "title": "Code Implementation", - "slug": "block-code", - "markdown_source": "../docs/getting-started/create-block/block-code.md", - "parent": "create-block" - }, - { - "title": "Authoring Experience", - "slug": "author-experience", - "markdown_source": "../docs/getting-started/create-block/author-experience.md", - "parent": "create-block" - }, - { - "title": "Finishing Touches", - "slug": "finishing", - "markdown_source": "../docs/getting-started/create-block/finishing.md", - "parent": "create-block" - }, - { - "title": "Share your Block with the World", - "slug": "submitting-to-block-directory", - "markdown_source": "../docs/getting-started/create-block/submitting-to-block-directory.md", - "parent": "create-block" - }, { "title": "Fundamentals of Block Development", "slug": "fundamentals", diff --git a/docs/toc.json b/docs/toc.json index 34be591647c174..fec39245761c94 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -21,31 +21,7 @@ ] }, { "docs/getting-started/quick-start-guide.md": [] }, - { - "docs/getting-started/create-block/README.md": [ - { - "docs/getting-started/create-block/wp-plugin.md": [] - }, - { - "docs/getting-started/create-block/block-anatomy.md": [] - }, - { - "docs/getting-started/create-block/attributes.md": [] - }, - { - "docs/getting-started/create-block/block-code.md": [] - }, - { - "docs/getting-started/create-block/author-experience.md": [] - }, - { - "docs/getting-started/create-block/finishing.md": [] - }, - { - "docs/getting-started/create-block/submitting-to-block-directory.md": [] - } - ] - }, + { "docs/getting-started/tutorial.md": [] }, { "docs/getting-started/fundamentals/README.md": [ {