Skip to content

Add functionality to a CMS

You will evaluate and add a table-of-contents plugin to a WordPress practice site, test its visitor behavior and dependency boundary, and prove that the configured site can be restored.

A CMS plugin adds or changes behavior beyond the CMS core and active theme. That capability also adds code, maintenance, security, privacy, compatibility, and removal responsibilities. The correct extension is the smallest maintained option that solves a defined visitor or editor need and has a tested recovery path.

What you will practice

  • Define a visitor need before selecting a CMS extension.
  • Compare core, theme, manual, plugin, and custom-code routes by fit and risk.
  • Evaluate current plugin identity, maintenance, compatibility, data, requests, and removal behavior.
  • Install and configure one plugin in a restored practice copy without changing the baseline.
  • Test generated in-page navigation with headings, URL fragments, keyboard use, narrow viewports, zoom, and browser tools.
  • Deactivate the plugin in a separate copy and document the site's dependency on it.
  • Export and restore a complete final checkpoint with the required plugin active.
  • New: Capability definition, plugin evaluation, WordPress Plugin Directory metadata, plugin installation and activation, generated blocks, dependency testing, deactivation behavior, frontend request inspection, privacy questions, and extension lifecycle evidence.
  • Reused: WordPress Playground, complete-site ZIPs, block editing, headings, anchor links, semantic lists, global theme styles, visitor testing, browser developer tools, documentation, .gitignore, and the solo Git workflow for text evidence.

Starting point

Before you start

  • The unchanged theme-customized-final.zip from the CMS theme lesson, or a teacher-provided equivalent ZIP.
  • A current version of Edge, Chrome, or Firefox with internet access.
  • VS Code and permission to create a local cms-functionality-practice folder.
  • Permission to install a teacher-approved plugin in a local practice site. Do not install it on a production site for this lesson.
Current state
You have a tested CMS theme result, but no separate functionality practice copy, plugin decision record, dependency test, or plugin-enabled final ZIP.
First action
Create cms-functionality-practice, copy theme-customized-final.zip into it without changing the original file, and rename the copy functionality-source.zip.
First checkpoint
cms-functionality-practice contains functionality-source.zip, and the unchanged theme-customized-final.zip still exists in its original folder.
Help trigger
Use the recovery note or ask for help if the source ZIP does not restore, plugin identity is ambiguous, installation requests an external account, the generated links do not reach their headings, deactivation makes content unreadable, or the final ZIP does not restore the active plugin and configured block.

The reference need is:

A visitor reading a long process guide must be able to scan its section structure and move directly to one section.

This lesson uses SimpleTOC – Table of Contents Block from the official WordPress Plugin Directory. It adds a block that generates a nested list of links from page headings.

Plugin metadata can change after this lesson is published. Read the current directory page before installation. Confirm the exact plugin name, author, directory URL, current version, last update, required WordPress and PHP versions, tested WordPress version, installation count, reviews, support activity, and changelog.

The directory description is evidence from the plugin publisher and WordPress.org records. It is not proof that the plugin works with this site, theme, browser, content, or assistive technology. The required tests provide that project-specific evidence.

If your teacher selects another plugin, keep the same capability and evidence contract. The alternative must create in-page navigation from headings, work in the native block editor, require no external account for the core feature, and have a reversible deactivation path.

You have completed the lesson when:

  • cms-functionality-practice contains functionality-source.zip, functionality-baseline.zip, functionality-configured.zip, functionality-final.zip, .gitignore, and cms-functionality-notes.md;
  • the source restores with the tested theme, routes, navigation, and media;
  • the notes define the visitor need and compare manual, core or theme, plugin, and custom-code routes;
  • the current official plugin metadata and identity are recorded before installation;
  • the reference plugin is installed and active only in the practice site;
  • a published Process Guide page contains an introduction, a table of contents, four H2 sections, and at least one H3 subsection;
  • every generated link reaches the matching heading and produces a useful URL fragment;
  • the table of contents uses list-and-link semantics, works with a keyboard, and remains usable at about 320px and 200% zoom;
  • browser tools show the plugin’s actual frontend requests and generated markup, including any unexpected external request or asset;
  • a separate copy remains readable after deactivation, and the notes identify exactly which capability disappears;
  • the configured plugin and page return after restoring functionality-final.zip; and
  • the notes are committed while all CMS ZIPs remain ignored and local.

Use this local structure:

CMS functionality practice files
cms-functionality-practice/
├── .gitignore
├── functionality-source.zip
└── cms-functionality-notes.md

Add this rule to .gitignore:

cms-functionality-practice/.gitignore
*.zip

Add this starting record to cms-functionality-notes.md:

cms-functionality-practice/cms-functionality-notes.md
# CMS extended functionality
## Capability
- Visitor:
- Need:
- Observable success:
- Out of scope:
## Alternatives
| Route | Fit | Added risk or work | Decision |
| --- | --- | --- | --- |
| Manual anchor list | | | |
| CMS core or active theme | | | |
| Plugin | | | |
| Custom plugin code | | | |
## Plugin evaluation
- Exact name:
- Author:
- Official directory URL:
- Version and last update checked on:
- Required and tested environments:
- Active installations, reviews, and support evidence:
- Data stored:
- Personal data handled:
- External services or requests:
- Frontend assets:
- Permissions or administration access:
- Deactivation and uninstall expectation:
- Update owner for a production site:
## Test evidence
| Condition | Expected result | Observed evidence | Pass or fix |
| --- | --- | --- | --- |
## Dependency test
- Result with plugin active:
- Result after deactivation:
- Content that remains:
- Capability that disappears:
- Recovery action:
## Restore verification
- Final ZIP:
- Plugin status after restore:
- Page and links compared:
- First mismatch, or none:
## Known limits
- Playground is a local practice environment, not a public production deployment.

Do not copy a plugin description into every field. Use the directory, administration screens, browser tools, and your own test results to distinguish claims from observed evidence.

Open a new WordPress Playground. Use New → Import zip in the Dock and select functionality-source.zip.

Before you install anything:

  1. Open the site root and every required visitor route.
  2. Test the primary navigation with the keyboard.
  3. Confirm the active block theme and saved global Styles.
  4. Confirm that required images and page headings remain present.
  5. Open Plugins → Installed Plugins and record the existing plugin list.
  6. Open the browser Network panel, reload one content page, and record the baseline request domains and relevant frontend assets.

Export the verified state as functionality-baseline.zip. Restore that ZIP in another new Playground and compare the site root, one child route, active theme, plugin list, navigation, and one image.

Checkpoint: The plugin test has a restorable baseline

What now works
functionality-source.zip remains unchanged, functionality-baseline.zip restores the verified site and plugin inventory, and the notes record the baseline routes and requests.
Files changed
cms-functionality-practice/functionality-source.zip, cms-functionality-practice/functionality-baseline.zip, cms-functionality-practice/cms-functionality-notes.md
What remains
Evaluate the extension against alternatives, then install it in the working practice site.
Next action
Open the official SimpleTOC directory page and complete every known evaluation field before selecting Install.
If it does not work
Compare the first failed baseline route with functionality-source.zip. Repair or replace the source before adding a plugin.

Do not begin with the plugin name. Begin with the visitor need.

A page author can add HTML anchors to headings and maintain a normal list of links. This route adds no plugin dependency, but each heading and list entry must stay synchronized through manual editing and review.

Inspect the current block inserter and theme features for a table-of-contents block or equivalent navigation. Use a core or already-approved theme capability when it meets the complete need. Do not add a duplicate plugin.

A focused plugin can generate the list from headings and update it as content changes. It adds a third-party code and maintenance dependency.

Custom code gives more control but creates ownership for secure implementation, validation, escaping, accessibility, compatibility, tests, updates, and removal. It is outside this lesson because the current goal is extension selection and integration, not PHP plugin development.

Complete the alternatives table. Select the reference plugin only if the site does not already provide an equivalent approved feature.

Open the official directory page and record the current values. Use these questions:

  • Does the administration search result match the exact name, author, and official directory page?
  • When was the plugin last updated?
  • Which WordPress and PHP versions does it require?
  • Which WordPress version does the publisher report as tested?
  • Does the changelog show current maintenance rather than only a recent version number?
  • Do support topics reveal a conflict relevant to this site or editor?
  • Does the plugin add only the required block, or several unrelated features?
  • Which content stores the plugin block?
  • What visitor output remains after deactivation?
  • Does uninstall remove settings, content markers, or data?
  • Can a manual anchor list replace the capability if maintenance stops?
  • Does the plugin collect or store personal data?
  • Does it contact an external service, load a remote asset, add telemetry, use cookies, or add browser storage?
  • Does the core feature require an account, license key, consent, or data transfer?
  • Which WordPress capability is required to install, configure, and use the block?

Mark an unanswered question as unknown. Do not convert missing documentation into a claim that no risk exists.

In the working restored Playground:

  1. Open Plugins → Add New Plugin.
  2. Search for the exact plugin name SimpleTOC – Table of Contents Block.
  3. Compare the author and details with the official directory record.
  4. Select Install Now only on the matching result.
  5. When installation completes, select Activate.
  6. Open Plugins → Installed Plugins and confirm that the plugin status is active.

If administration search or networking is unavailable, download the plugin ZIP from the official WordPress.org directory and use the administration upload route approved by your teacher. Do not use a third-party download mirror.

Stop if installation requests an external account, unrelated plugin, or broader feature bundle that was not part of the recorded evaluation.

Before you create content:

  • reload the existing visitor routes;
  • confirm that page content, theme presentation, and navigation still work;
  • compare the Network panel with the baseline; and
  • record any new request, script, stylesheet, cookie, storage entry, or external domain.

An absent difference in one route is limited evidence. The plugin’s block has not been placed yet.

Create a page named Process Guide. Use the page title as the only H1.

Add these blocks in order:

  1. A short introduction: Use this guide to move from a defined requirement to verified project evidence.
  2. The SimpleTOC table-of-contents block.
  3. An H2 named Plan the required result and one explanatory paragraph.
  4. An H2 named Build the smallest complete path and one explanatory paragraph.
  5. An H3 named Record a working checkpoint and one explanatory paragraph.
  6. An H2 named Test observable behavior and one explanatory paragraph.
  7. An H2 named Document evidence and limits and one explanatory paragraph.

Configure the table of contents to include headings through level H3. Use an ordered or unordered list. Keep the generated heading label visible unless you add an equivalent visible heading immediately before the block.

Publish the page. Open the visitor result in a new tab.

For each generated link:

  1. Read its text and identify the matching heading.
  2. Activate it with the keyboard.
  3. Confirm that the browser moves to the correct heading.
  4. Confirm that the address contains a fragment after #.
  5. Reload that fragment URL and confirm that the same heading remains the target.
  6. Confirm that focus and reading order remain understandable after the move.

Use the Elements or Inspector panel to confirm that the table of contents contains a semantic list of links. Record the observed wrapper, list, links, heading IDs, and URL fragments. Do not record the plugin directory’s accessibility statement as your test result.

Add one more H2 named Share the result, followed by a paragraph. Update and reload the visitor page. Confirm that one new table-of-contents link appears and reaches the new heading without manually editing the list.

Remove the added section again. Confirm that its generated link also disappears.

Checkpoint: The extension solves the defined visitor need

What now works
Process Guide renders a generated list from H2 and H3 headings, every keyboard-operated link reaches its matching fragment target, and heading additions and removals update the list.
What remains
Inspect the frontend cost, test deactivation in a separate copy, then export and restore the active final state.
Next action
Run the complete visitor and Network test matrix, then export the active configured site as functionality-configured.zip.
If it does not work
Check the heading levels, block depth setting, saved page state, and first incorrect fragment before reinstalling or replacing the plugin.

Test accessibility, layout, and frontend cost

Section titled “Test accessibility, layout, and frontend cost”

Add these conditions to the notes:

Condition Expected result
Process Guide at a wide viewport Table of contents shows the correct nested section structure
Process Guide at about 320px Link text wraps without horizontal overflow or clipped targets
Process Guide at 200% zoom Content reflows and every generated link remains operable
Keyboard from page start Every table-of-contents link receives visible focus in a logical order
Fragment URL loaded directly The matching heading is present and not hidden by the shared header
Screen-reader or accessibility-tree inspection The result exposes useful navigation, list, link, and heading semantics
Network panel with cache disabled Requests and transferred assets are recorded and compared with baseline
Console after interaction No new JavaScript error appears

The plugin directory can describe default asset behavior. Record what this configured page actually requests. If the page contacts an unexpected third-party domain or loads an unexplained asset, stop and investigate before approval.

Export the active configured working site as functionality-configured.zip.

Restore functionality-configured.zip in a separate Playground. In that separate copy:

  1. Open Process Guide and record the active result.
  2. Open Plugins → Installed Plugins and deactivate the reference plugin. Do not delete it.
  3. Reload Process Guide in the visitor view.
  4. Record which page content remains, which table-of-contents capability disappears or changes, and whether an unsupported-block message appears in the editor.
  5. Confirm that other routes, theme presentation, navigation, headings, and paragraphs remain readable.
  6. Reactivate the plugin and confirm that the configured table of contents returns after a page reload.

Do not perform this test in the only configured working copy. Deactivation is reversible, but it changes the site state and can affect saved editor behavior.

Document the exact dependency. A statement such as “the plugin is required” is incomplete. Name the block, visitor output, saved content, fallback behavior, and recovery action.

Return to the working site where the plugin remains active and every test passes.

  1. Confirm the plugin is active and Process Guide is published.
  2. Export the complete Playground as a ZIP.
  3. Store it as functionality-final.zip.
  4. Open a new Playground and restore functionality-final.zip.
  5. Confirm the active plugin identity and status.
  6. Open Process Guide and test the generated links, fragments, hierarchy, narrow layout, and keyboard path.
  7. Check another route to confirm that the theme and navigation remain correct.
  8. Record the first mismatch, or none, in the notes.

Commit only .gitignore and cms-functionality-notes.md in the private practice repository. Use git status --ignored to confirm that all four ZIP files remain local and ignored.

Self-check

Complete these checks against the required result.

  1. Confirm that functionality-source.zip, functionality-baseline.zip, functionality-configured.zip, and functionality-final.zip are separate local files greater than 0 bytes.
  2. State the visitor need without naming the plugin, then explain why the selected route fits better than the recorded alternatives.
  3. Compare the installed plugin name and author with the current official directory record.
  4. Show the current maintenance, compatibility, support, data, request, permission, and removal evidence in the notes, including every unknown.
  5. Open Process Guide and confirm one H1 page title, four H2 sections, at least one H3 subsection, and the generated table of contents.
  6. Use the keyboard to activate every generated link and confirm the matching heading and URL fragment.
  7. Test the page at about 320px and 200% zoom and confirm readable wrapping, visible focus, and no horizontal overflow.
  8. Compare the Network and Console evidence with the baseline and explain every plugin-related difference you observed.
  9. Show the separate deactivation result and name the exact content that remains, capability that disappears, and recovery action.
  10. Restore functionality-final.zip and confirm that the active plugin and configured page return without a mismatch.
  11. Run git status and git status --ignored and confirm that the notes are committed while every ZIP remains ignored and local.
Symptom Likely cause Focused check
The plugin cannot be found Search, networking, or plugin identity is wrong Compare the official name, author, slug, and directory URL
The block is absent after activation The page uses another editor or activation did not complete Confirm the native block editor and Installed Plugins status
The table is empty The page has no included heading levels or changes are unsaved Inspect H2 and H3 blocks, depth settings, and publication state
A generated link reaches the wrong place Heading anchors are repeated or stale Inspect heading IDs and the exact fragment in the rendered link
A heading is hidden after a link The shared header overlays the fragment target Test direct fragment loading and inspect header positioning
Deactivation makes the editor warn about a block Saved content depends on a plugin-provided block Record the dependency and reactivate in the test copy before editing
The final restore lacks the plugin The wrong ZIP was exported or export occurred before activation Compare filenames, plugin status, and export order
Requests reach an unexplained domain The plugin, another extension, or page content adds an external resource Match the request initiator and stop until the data flow is understood

The required lesson is complete when the extension solves the defined need, the visitor and request evidence passes, the separate deactivation test documents the dependency, and functionality-final.zip restores the active configured result.

Continue to Practice: Extend a CMS site to select and integrate a CMS capability for an independent site brief with the same evaluation and recovery contract.

If you stop here, leave yourself this resume note beside the final ZIP: The table-of-contents capability is evaluated, tested, deactivation-aware, and restorable. Next, open the CMS extension assignment and define the visitor or editor need before selecting a solution.