From 82e2ec88f5790cc523ef4f7116f2255a6233c907 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 13 Oct 2025 20:32:29 +0200 Subject: [PATCH 01/29] add disabling webtools warning --- packages/docs/docs/getting-started/usage.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/docs/docs/getting-started/usage.md b/packages/docs/docs/getting-started/usage.md index 28eec2f7..92dc0990 100644 --- a/packages/docs/docs/getting-started/usage.md +++ b/packages/docs/docs/getting-started/usage.md @@ -55,10 +55,27 @@ pluginOptions: { After enabling Webtools for your content types: 1. **Create URL patterns** - See [URL pattern](/url-pattern) documentation -2. **Bulk generate URLs** - Go to Webtools > All URLs to create aliases for existing content +2. **Bulk generate URLs** - Go to Webtools > All URLs to create aliases for existing content 3. **Generate sitemap** - Configure and generate XML sitemap with your URLs :::tip Pattern discovery Type `[` in the pattern field to see available fields from your content type. ::: +## Disabling Webtools + +:::warning Data Loss Warning +Disabling Webtools for a content type will permanently delete all URL aliases associated with that content type. This action cannot be undone. +::: + +To disable Webtools for a content type: + +1. Go to **Content-Type Builder** +2. Select the content type +3. Click **Edit** +4. Go to **Advanced Settings** tab +5. Uncheck **Webtools** +6. Confirm the deletion warning + +The system will prompt you to confirm before deleting all paths. + From 0c518e6d07c6555c4da0ee3745fa0fdb34b6032c Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 13 Oct 2025 21:16:48 +0200 Subject: [PATCH 02/29] when disabling webtools --- packages/docs/docs/getting-started/usage.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/docs/docs/getting-started/usage.md b/packages/docs/docs/getting-started/usage.md index 92dc0990..6514e869 100644 --- a/packages/docs/docs/getting-started/usage.md +++ b/packages/docs/docs/getting-started/usage.md @@ -68,6 +68,11 @@ Type `[` in the pattern field to see available fields from your content type. Disabling Webtools for a content type will permanently delete all URL aliases associated with that content type. This action cannot be undone. ::: +When you disable Webtools: + +- `pluginOptions.webtools.enabled` is set to `false` in the schema +- All URL aliases for this content type are deleted from the database + To disable Webtools for a content type: 1. Go to **Content-Type Builder** From 522f80999f0069908dddb954ce45fd4b2fabdc98 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 13 Oct 2025 21:20:41 +0200 Subject: [PATCH 03/29] clarify package names --- packages/docs/docs/getting-started/installation.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/docs/docs/getting-started/installation.md b/packages/docs/docs/getting-started/installation.md index 8b1c4aca..9c45ac2e 100644 --- a/packages/docs/docs/getting-started/installation.md +++ b/packages/docs/docs/getting-started/installation.md @@ -23,6 +23,11 @@ To install the plugin run the following command in your Strapi project directory npx webtools-cli install ``` +:::note Package names +- **webtools-cli** - Interactive installer that sets up Webtools +- **strapi-plugin-webtools** - The actual Strapi plugin (installed by the CLI) +::: + ### Command Line Interface (installer) During installation the Webtools CLI guides you through a short wizard: From 9483483d704dcff7d3a8bebc30ec013b7cb46ae9 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 13 Oct 2025 22:04:26 +0200 Subject: [PATCH 04/29] add update/ after update instructions --- .../docs/docs/getting-started/installation.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/docs/docs/getting-started/installation.md b/packages/docs/docs/getting-started/installation.md index 9c45ac2e..90cdab9a 100644 --- a/packages/docs/docs/getting-started/installation.md +++ b/packages/docs/docs/getting-started/installation.md @@ -74,3 +74,43 @@ After successful installation you have to rebuild the admin UI so it'll include - Enable Webtools per content type → see [Usage](/webtools/usage) - Review Roles & Permissions → see [Permissions](/webtools/permissions) + +## Updating Webtools + +### Update to latest version + +To update Webtools to the latest version, use your package manager: + + + + ``` + yarn upgrade strapi-plugin-webtools + ``` + + + ``` + npm update strapi-plugin-webtools + ``` + + + +After updating, rebuild the admin UI: + + + + ``` + yarn build + yarn develop + ``` + + + ``` + npm run build + npm run develop + ``` + + + +:::tip Enable additional content types +To enable Webtools for additional content types after installation, see the [Usage documentation](/webtools/usage#enabling-webtools). +::: From 101aa4b382913ca705bf194f0c132dedecc86a51 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:22:12 +0200 Subject: [PATCH 05/29] Expand setup-license CLI documentation Added detailed instructions for setting up a license using the CLI, including options for entering a license key, starting a free trial, or skipping setup. Clarified which files are updated for different package managers and provided next steps for addon installation. --- packages/docs/docs/cli/setup-license.md | 77 ++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/cli/setup-license.md b/packages/docs/docs/cli/setup-license.md index 4f1df7d7..2e0053cb 100644 --- a/packages/docs/docs/cli/setup-license.md +++ b/packages/docs/docs/cli/setup-license.md @@ -8,10 +8,83 @@ slug: /cli/setup-license ## Overview -If you've purchased a license for the premium features of Webtools you can use this CLI to setup the configuration for proper installation and license validation. The CLI will ask you to input your license key which will be added to the `.npmrc` and `.env` files. +If you've purchased a license for the premium features of Webtools, or want to start a free trial, you can use this CLI to setup the configuration for proper installation and license validation. The CLI will ask you to input your license key which will be added to the `.npmrc` (or `.yarnrc.yml` for Yarn v2+) and `.env` files. ## Usage -``` +```bash npx webtools-cli setup-license ``` + +## License Setup Options + +When you run the setup command, you'll be presented with three options: + +### 1. Yes, use my license + +Select this option if you already have a purchased license key. You'll be prompted to: +- Enter your license key +- The CLI will automatically create/update: + - `.env` file with `WEBTOOLS_LICENSE_KEY=your-key` + - `.npmrc` file (for npm/pnpm/Yarn v1) or `.yarnrc.yml` file (for Yarn v2+) with registry configuration + +### 2. Get me a trial + +Select this option to start a **30-day free trial** of the Essential plan. The trial includes: +- [Redirects addon](/webtools/addons/redirects) +- [Internal Links addon](/webtools/addons/links) + +#### Trial Process + +1. The CLI will display a link to start your free trial +2. Visit the link to complete the checkout process +3. After checkout, you'll receive your trial license key +4. Return to the CLI and select "Yes" when asked "Got your license key?" +5. Enter your license key to complete the setup + +:::tip +Remember: You can cancel within 7 days to ensure your trial remains free. +::: + +### 3. Skip + +Select this option if you want to continue without setting up a license. You'll have access to: +- Core Webtools features (URL aliases and patterns) +- [Sitemap addon](/webtools/addons/sitemap) (free) + +## What Gets Created + +The setup process creates/updates the following files: + +### .env file + +``` +WEBTOOLS_LICENSE_KEY=your-license-key-here +``` + +### .npmrc file (npm/pnpm/Yarn v1) + +``` +@pluginpal:registry=https://npm.pluginpal.io +//npm.pluginpal.io/:_authToken=your-license-key-here +always-auth=true +``` + +### .yarnrc.yml file (Yarn v2+) + +```yaml +npmScopes: + pluginpal: + npmPublishRegistry: https://npm.pluginpal.io + npmRegistryServer: https://npm.pluginpal.io + npmAlwaysAuth: true + npmAuthIdent: "token" + npmAuthToken: "your-license-key-here" +``` + +## Next Steps + +After setting up your license, follow the installation instructions for the addons you want to use: + +- [Redirects addon installation](/webtools/addons/redirects/installation) +- [Links addon installation](/webtools/addons/links/installation) From 91b5d7c1a26953e7ed9304cdf5b01e762895157c Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:42:36 +0200 Subject: [PATCH 06/29] Add troubleshooting steps for license activation issues Documents solutions for license key activation errors, including how to remove the activation_id from package.json and re-activate the license. Provides example configurations and additional tips for resolving persistent activation problems. --- .../docs/getting-started/troubleshooting.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/packages/docs/docs/getting-started/troubleshooting.md b/packages/docs/docs/getting-started/troubleshooting.md index 2e1017ab..c1a5dc4b 100644 --- a/packages/docs/docs/getting-started/troubleshooting.md +++ b/packages/docs/docs/getting-started/troubleshooting.md @@ -26,6 +26,63 @@ Multiple warnings about unmet peer dependencies during installation. **Solution:** These warnings are normal and won't affect functionality. The plugin will work correctly despite these warnings. +## License Issues + +### License key activation is not valid +``` +error: [webtools]: License key activation is not valid. Remove the activation_id from your package.json to issue a new activation for this project. +``` + +This error occurs when the stored license activation is no longer valid. This can happen when: + +- You moved the project to a different machine +- You reinstalled dependencies or changed the project structure +- Your license has expired or been deactivated +- You've reached the maximum number of activations for your license + +**Solution:** Remove the activation ID and restart Strapi to trigger a new activation: + +1. Open your `package.json` file +2. Look for a field named `activation_id` (usually near the top level) +3. Remove the entire `activation_id` field and its value +4. Save the file +5. Restart your Strapi server + +The plugin will automatically create a new activation on the next startup. + +**Example:** + +Before: +```json +{ + "name": "my-strapi-project", + "activation_id": "abc123...", + "version": "1.0.0", + ... +} +``` + +After: +```json +{ + "name": "my-strapi-project", + "version": "1.0.0", + ... +} +``` + +:::tip +If you continue to experience activation issues after removing the `activation_id`, ensure your license key is correctly set in the `.env` file: +``` +WEBTOOLS_LICENSE_KEY=your-license-key-here +``` + +You can also re-run the license setup: +```bash +npx webtools-cli setup-license +``` +::: + ## Pattern & URL Issues ### URL is incorrect From f56380986b54945915d2a1d208e33255e381358e Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:59:35 +0200 Subject: [PATCH 07/29] Add redirect URL format and status code guidelines Expanded the usage documentation for the redirects addon with detailed instructions on URL path formatting and HTTP status code selection. Includes examples and tips to help users choose the correct redirect type and understand SEO and caching implications. --- .../addons/redirects/getting-started/usage.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/docs/docs/addons/redirects/getting-started/usage.md b/packages/docs/docs/addons/redirects/getting-started/usage.md index 378ac723..74215d76 100644 --- a/packages/docs/docs/addons/redirects/getting-started/usage.md +++ b/packages/docs/docs/addons/redirects/getting-started/usage.md @@ -19,6 +19,51 @@ With the button in the top right you can create new redirects. Create redirects +### URL Format + +When creating redirects, follow these guidelines for the URL paths: + +**From Path (Source URL):** +- Always start with a forward slash `/` +- Use relative paths only (no domain) +- Example: `/old-page` or `/blog/old-article` + +**To Path (Destination URL):** +- For internal redirects: use relative paths starting with `/` + - Example: `/new-page` or `/blog/new-article` +- For external redirects: use the full URL including protocol + - Example: `https://example.com/page` + +**Examples:** + +| From Path | To Path | Description | +|-----------|---------|-------------| +| `/old-page` | `/new-page` | Internal redirect | +| `/blog/article` | `/news/article` | Internal redirect to different section | +| `/external` | `https://example.com` | External redirect | + +### Status Codes + +Choose the appropriate HTTP status code for your redirect: + +| Status Code | Name | Description | Use Case | +|-------------|------|-------------|----------| +| **301** | Permanent Redirect | The resource has been permanently moved to a new location. Search engines will transfer the SEO value to the new URL. | Use when a page has permanently moved and you want to preserve SEO rankings. | +| **302** | Temporary Redirect | The resource is temporarily at a different location. Search engines keep the original URL indexed. | Use for temporary changes, A/B testing, or maintenance pages. | +| **303** | See Other | The response to the request can be found at another URL using a GET request. | Use after POST/PUT requests to redirect to a confirmation page. | +| **307** | Temporary Redirect (Preserve Method) | Like 302, but guarantees the request method won't change. | Use when you need to preserve POST/PUT methods in the redirect. | +| **308** | Permanent Redirect (Preserve Method) | Like 301, but guarantees the request method won't change. | Use for permanent redirects where the request method must be preserved. | + +:::tip Choosing the Right Status Code +- **Most common:** Use **301** for permanent redirects and **302** for temporary ones +- **SEO impact:** 301 redirects transfer ~90-99% of link equity to the new URL +- **Caching:** 301 redirects are cached by browsers, 302 redirects are not +::: + +:::caution +Be careful with 301 redirects as they are heavily cached by browsers. If you need to change a 301 redirect, users may not see the change immediately due to browser caching. +::: + ## Access After you've followed the steps above you can now access your sitemap through the REST api of strapi. It will be available at: From 70a2ccb5853122719b03ccd62bc42debf75ab1c5 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:16:44 +0200 Subject: [PATCH 08/29] Expand docs for auto-generate and status code options Enhanced the documentation for the auto-generate feature in redirects addon with detailed explanations, use cases, and scenarios. Updated the sidebar label for the default-status-code configuration page to accurately reflect its content. --- .../redirects/configuration/auto-generate.md | 54 ++++++++++++++++++- .../configuration/default-status-code.md | 2 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/addons/redirects/configuration/auto-generate.md b/packages/docs/docs/addons/redirects/configuration/auto-generate.md index 229c20ca..9c543c58 100644 --- a/packages/docs/docs/addons/redirects/configuration/auto-generate.md +++ b/packages/docs/docs/addons/redirects/configuration/auto-generate.md @@ -6,7 +6,59 @@ slug: /addons/redirects/configuration/auto-generate # Auto generate -When this option is set to true (which it is by default) the addon will automatically generate a redirect whenever you change the URL alias of a page. This way you will never have dead links in your website! +## Overview + +The auto-generate feature automatically creates redirects whenever you change the URL alias of a content entry in your Strapi application. This ensures visitors following old links will be seamlessly redirected to the new URL without encountering broken links or 404 errors. + +## How it works + +When enabled (which it is by default), the addon monitors URL alias changes and creates redirect entries automatically: + +1. You change a page's URL from `/old-blog-post` to `/new-blog-post` +2. The addon detects this change +3. A redirect is automatically created: `/old-blog-post` → `/new-blog-post` +4. Visitors using the old URL are redirected to the new location + +## Why use this? + +**Preserves SEO rankings**: Search engines have indexed your old URLs. Redirects ensure you don't lose search engine rankings when changing URLs. + +**Prevents broken links**: External sites, bookmarks, and shared links pointing to your old URLs continue to work. + +**Improves user experience**: Visitors are automatically sent to the correct page instead of seeing a 404 error. + +**Saves time**: No need to manually track and create redirects for every URL change. + +## Example scenario + +Imagine you have a blog post at `/blog/how-to-use-strapi` that's been shared widely and indexed by Google. Later, you decide to rename it to `/blog/complete-strapi-guide`. + +**With auto-generate enabled:** +- You update the URL alias in Strapi +- A redirect is automatically created +- Old links continue to work +- Your SEO rankings are preserved + +**With auto-generate disabled:** +- You update the URL alias in Strapi +- Old links lead to 404 errors +- You lose traffic from external links +- You have to manually create redirects + +## When to disable + +You might want to disable auto-generate if: +- You want full manual control over all redirects +- You're doing bulk URL changes and want to review redirects afterwards +- You're migrating content and have a custom redirect strategy + +:::tip +Keep this enabled for production sites. It's a safety net that prevents broken links automatically. +::: + +## Difference from sitemap cron + +Unlike the sitemap addon which uses a cron job to periodically regenerate files, redirects are created **instantly** when you change a URL. There's no delay and no need for scheduled tasks - redirects are event-driven and created the moment you save your changes. ###### Key: `auto_generate ` diff --git a/packages/docs/docs/addons/redirects/configuration/default-status-code.md b/packages/docs/docs/addons/redirects/configuration/default-status-code.md index 2327426b..d0a49362 100644 --- a/packages/docs/docs/addons/redirects/configuration/default-status-code.md +++ b/packages/docs/docs/addons/redirects/configuration/default-status-code.md @@ -1,5 +1,5 @@ --- -sidebar_label: 'Cron' +sidebar_label: 'Default status code' displayed_sidebar: webtoolsRedirectsSidebar slug: /addons/redirects/configuration/default-status-code --- From 26f5df1a97be814ae511ac1a703abb9b6f5a6065 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:40:34 +0100 Subject: [PATCH 09/29] Removed Might have and sitemap reference --- packages/docs/docs/addons/redirects/getting-started/usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/addons/redirects/getting-started/usage.md b/packages/docs/docs/addons/redirects/getting-started/usage.md index 74215d76..b97594b0 100644 --- a/packages/docs/docs/addons/redirects/getting-started/usage.md +++ b/packages/docs/docs/addons/redirects/getting-started/usage.md @@ -65,10 +65,10 @@ Be careful with 301 redirects as they are heavily cached by browsers. If you nee ::: ## Access -After you've followed the steps above you can now access your sitemap through the REST api of strapi. It will be available at: +After you've followed the steps above you can now access your redirects through the REST API of Strapi. It will be available at: http://localhost:1337/api/webtools/redirects. :::caution -You might have to setup permissions for this endpoint to be accessible. +You need to setup permissions for this endpoint to be accessible. See the [REST API documentation](/webtools/addons/redirects/api/rest#permissions) for details. ::: From 829d440a4885d0c6fc477cf1730e0ef9dc1797e3 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:50:19 +0100 Subject: [PATCH 10/29] Made permissions more outstanding in docs --- .../docs/docs/addons/redirects/api/rest.md | 17 ++++++------ packages/docs/docs/api/rest.md | 27 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/docs/docs/addons/redirects/api/rest.md b/packages/docs/docs/addons/redirects/api/rest.md index 6ef5dfec..aaf6a2f1 100644 --- a/packages/docs/docs/addons/redirects/api/rest.md +++ b/packages/docs/docs/addons/redirects/api/rest.md @@ -14,6 +14,15 @@ The plugin exposes a REST API endpoint that you can use to implement the redirec Use Public role or API Tokens as per Strapi defaults. +### Permissions + +:::danger Permissions Required +Before you can use the redirects endpoint publicly, you need to configure the **find** permission. Without proper permissions, you'll get a **403 Forbidden** error. + +**Quick Setup in Settings > Users & Permissions > Roles > Public:** +- `webtools-addon-redirects.redirect.find` +::: + @@ -71,11 +80,3 @@ Use Public role or API Tokens as per Strapi defaults. -## Permissions - -Before you can use the redirects endpoint publicly, you need to configure the *find* permission. - -### Quick Setup - -Enable in **Settings > Users & Permissions > Roles > Public**: -- `webtools-addon-redirects.redirect.find` diff --git a/packages/docs/docs/api/rest.md b/packages/docs/docs/api/rest.md index 99848ef6..6cad3da6 100644 --- a/packages/docs/docs/api/rest.md +++ b/packages/docs/docs/api/rest.md @@ -14,6 +14,19 @@ The plugin exposes a couple of REST API endpoints that you can use to implement Use Public role or API Tokens as per Strapi defaults. +### Permissions + +:::danger Permissions Required +Before you can use the router and url-alias endpoints publicly, you need to configure the **find** permissions. Without proper permissions, you'll get a **403 Forbidden** error. + +**Quick Setup in Settings > Users & Permissions > Roles > Public:** +- `webtools.url-alias.find` +- `webtools.router.find` +- For each enabled content type: `[content-type].find` + +See the complete [Permissions Guide](/permissions) for detailed instructions on all three permission levels. +::: + ## Router Probably the most important endpoint of the plugin is it's router endpoint. @@ -156,17 +169,3 @@ The query parameter `?url_path=` does not work correctly. Always use the full fi -## Permissions - -Before you can use the router and url-alias endpoints publicly, you need to configure the *find* permissions. - -### Quick Setup - -Enable in **Settings > Users & Permissions > Roles > Public**: -- `webtools.url-alias.find` -- `webtools.router.find` - -For each enabled content type, also enable: -- `[content-type].find` - -See [Permissions](/permissions) for a complete explanation of all three permission levels that need to be configured. From b899a14da9e4d522e4baa86a487d352478ba6c2b Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:11:23 +0100 Subject: [PATCH 11/29] Document redirect chains, loops, and auto-generate behavior --- .../redirects/configuration/auto-generate.md | 38 +++++++ .../redirects/getting-started/introduction.md | 10 +- .../addons/redirects/getting-started/usage.md | 98 +++++++++++++++++++ 3 files changed, 141 insertions(+), 5 deletions(-) diff --git a/packages/docs/docs/addons/redirects/configuration/auto-generate.md b/packages/docs/docs/addons/redirects/configuration/auto-generate.md index 9c543c58..a665c748 100644 --- a/packages/docs/docs/addons/redirects/configuration/auto-generate.md +++ b/packages/docs/docs/addons/redirects/configuration/auto-generate.md @@ -56,6 +56,44 @@ You might want to disable auto-generate if: Keep this enabled for production sites. It's a safety net that prevents broken links automatically. ::: +## Multiple URL Changes + +When you change the same URL multiple times, the addon intelligently manages redirects to prevent chains: + +**Scenario 1: First URL change** +``` +Original URL: /my-article +New URL: /my-article-updated + +Result: Creates redirect /my-article → /my-article-updated ✓ +``` + +**Scenario 2: Second URL change (updates existing redirect)** +``` +Current URL: /my-article-updated +New URL: /my-article-final + +Result: +- Updates existing redirect to: /my-article → /my-article-final ✓ +- Creates new redirect: /my-article-updated → /my-article-final ✓ +``` + +This strategy prevents redirect chains and ensures all old URLs point directly to the current URL. Both `/my-article` and `/my-article-updated` will redirect straight to `/my-article-final` without intermediate hops. + +:::tip Smart Redirect Management +The addon automatically updates existing redirects that point to the old URL, ensuring no chains are created. This means you can freely change URLs multiple times without worrying about redirect performance. +::: + +## Chain Prevention + +Auto-generate includes built-in protection against [redirect chains and loops](/addons/redirects/usage#redirect-chains-and-loops). If a URL change would create a chain or loop, the system will: + +1. **Log an error** in your server console +2. **Skip creating the redirect** automatically +3. **Allow you to manually resolve** the conflict + +Check your server logs if you suspect redirects aren't being created as expected. + ## Difference from sitemap cron Unlike the sitemap addon which uses a cron job to periodically regenerate files, redirects are created **instantly** when you change a URL. There's no delay and no need for scheduled tasks - redirects are event-driven and created the moment you save your changes. diff --git a/packages/docs/docs/addons/redirects/getting-started/introduction.md b/packages/docs/docs/addons/redirects/getting-started/introduction.md index 501bd6f9..1ccb1c03 100644 --- a/packages/docs/docs/addons/redirects/getting-started/introduction.md +++ b/packages/docs/docs/addons/redirects/getting-started/introduction.md @@ -14,9 +14,9 @@ This plugin acts as an extension of the core `strapi-plugin-webtools`. Please in ## ✨ Features -- **Automatic creation** (Automatic redirect creation when your URL changes) -- **Chain detection** (Prevents you from creating redirects that create chains) -- **Loop detection** (Prevents you from creating redirects that create loops) -- **Custom redirects** (Create custom redirects, separate from Webtools pages) -- **API endpoint** (Fetch and use the redirects in your front-end) +- **Automatic creation** - Automatic redirect creation when your URL changes ([learn more](/addons/redirects/configuration/auto-generate)) +- **Chain detection** - Prevents you from creating redirects that create chains ([what are chains?](/addons/redirects/usage#what-is-a-redirect-chain)) +- **Loop detection** - Prevents you from creating redirects that create loops ([what are loops?](/addons/redirects/usage#what-is-a-redirect-loop)) +- **Custom redirects** - Create custom redirects, separate from Webtools pages +- **API endpoint** - Fetch and use the redirects in your front-end ([REST API docs](/addons/redirects/api/rest)) diff --git a/packages/docs/docs/addons/redirects/getting-started/usage.md b/packages/docs/docs/addons/redirects/getting-started/usage.md index b97594b0..e98e1b0a 100644 --- a/packages/docs/docs/addons/redirects/getting-started/usage.md +++ b/packages/docs/docs/addons/redirects/getting-started/usage.md @@ -64,6 +64,104 @@ Choose the appropriate HTTP status code for your redirect: Be careful with 301 redirects as they are heavily cached by browsers. If you need to change a 301 redirect, users may not see the change immediately due to browser caching. ::: +## Redirect Chains and Loops + +The Webtools Redirects addon includes built-in protection against redirect chains and loops, which can harm user experience and SEO. + +### What is a Redirect Chain? + +A **redirect chain** occurs when multiple redirects are needed to reach the final destination. This creates an inefficient path that slows down page loads. + +**Example of a chain:** +``` +/page-a → /page-b → /page-c (final destination) +``` + +When a user visits `/page-a`, they are first redirected to `/page-b`, then redirected again to `/page-c`. This requires two HTTP requests instead of one. + +**Why chains are problematic:** +- **Slower page loads**: Each redirect adds network latency +- **SEO penalties**: Search engines may not follow long chains and could lose link equity +- **User experience**: Visitors experience longer wait times +- **Server load**: More requests mean more server resources + +**Best practice:** Always redirect directly to the final destination: +``` +/page-a → /page-c +/page-b → /page-c +``` + +### What is a Redirect Loop? + +A **redirect loop** occurs when redirects create a circular reference with no final destination. + +**Example of a loop:** +``` +/page-a → /page-b → /page-a (back to start) +``` + +This creates an infinite loop where the browser keeps redirecting between pages until it gives up and shows an error. + +**Why loops are critical:** +- **Broken website**: The page becomes completely inaccessible +- **Browser errors**: Users see "Too many redirects" or "Redirect loop detected" +- **SEO disaster**: Search engines cannot index the page + +### Chain and Loop Detection + +The addon automatically validates redirects and **prevents you from creating chains or loops**. If you try to create a redirect that would result in a chain or loop, you'll see an error: + +``` +Creating this redirect would create a chain, please change it. +``` + +**Common scenarios that trigger this error:** + +1. **Existing redirect path:** You try to create a redirect where the "To" path is already the "From" path of another redirect + + ``` + Existing: /old-page → /new-page + Attempt: /campaign → /old-page ❌ (would create chain) + ``` + +2. **Reverse redirect:** You try to create a redirect that reverses an existing one + + ``` + Existing: /page-a → /page-b + Attempt: /page-b → /page-a ❌ (would create loop) + ``` + +3. **URL alias conflict:** You change a URL alias to a path that's involved in an existing redirect + + ``` + Existing redirect: /google → /google5 + Changing URL alias from /google5 to /google ❌ (would create conflict) + ``` + +### How to Fix Chain/Loop Errors + +**If you encounter this error:** + +1. **Check existing redirects**: Review your redirect list for conflicts +2. **Update existing redirects**: Instead of creating a new redirect, update the existing one to point directly to the final destination +3. **Delete conflicting redirects**: Remove the redirect that's causing the chain, then create a new direct redirect +4. **Plan URL changes carefully**: Before changing URL aliases, check if redirects exist for those paths + +**Example fix:** + +``` +Problem: + - Existing redirect: /old → /current + - You want to change URL from /current to /new + - This would create: /old → /current → /new ❌ + +Solution: + 1. Update the existing redirect to: /old → /new + 2. Then change the URL alias to /new + 3. Auto-generate creates: /current → /new + 4. Result: /old → /new and /current → /new ✓ +``` + ## Access After you've followed the steps above you can now access your redirects through the REST API of Strapi. It will be available at: From 8a48fd0a348d811fdc5b32114498221e94817555 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:45:30 +0100 Subject: [PATCH 12/29] Added some docs for frontend implementation. --- .../addons/redirects/getting-started/usage.md | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/docs/docs/addons/redirects/getting-started/usage.md b/packages/docs/docs/addons/redirects/getting-started/usage.md index e98e1b0a..5921a643 100644 --- a/packages/docs/docs/addons/redirects/getting-started/usage.md +++ b/packages/docs/docs/addons/redirects/getting-started/usage.md @@ -64,6 +64,50 @@ Choose the appropriate HTTP status code for your redirect: Be careful with 301 redirects as they are heavily cached by browsers. If you need to change a 301 redirect, users may not see the change immediately due to browser caching. ::: +## Access +After you've followed the steps above you can now access your redirects through the REST API of Strapi. It will be available at: + +http://localhost:1337/api/webtools/redirects. + +:::caution +You need to setup permissions for this endpoint to be accessible. See the [REST API documentation](/webtools/addons/redirects/api/rest#permissions) for details. +::: + +## Frontend Implementation + +Now that you have access to the redirects API, you need to implement the redirects in your frontend. There are two approaches: + +### Option 1: Framework Redirects Configuration + +Most modern frameworks have built-in redirect features (Next.js, Nuxt, etc.). You can fetch redirects from the Strapi API and configure them in your framework's configuration file. + +**Note:** This approach is framework-specific and requires different setup for each framework. Consult your framework's documentation for redirect configuration. + +### Option 2: API Check Before Router (Recommended) + +The recommended approach is to check for redirects **before** calling the Webtools router endpoint. This works consistently across all frameworks and tech stacks. + +**Flow:** +1. User navigates to a URL (e.g., `/old-page`) +2. Your frontend calls the redirects API: `GET /api/webtools/redirects` +3. Check if the current path matches any redirect's `from` field +4. **If redirect exists:** Navigate to the `to` URL with the appropriate status code +5. **If no redirect:** Proceed to call the Webtools router endpoint: `GET /api/webtools/router?path=/old-page` + +**Why this works:** +- Framework-agnostic solution +- Works with the [Webtools router endpoint](/api/rest#router) pattern you're already using +- Ensures redirects are checked before attempting to fetch content +- No need for complex server middleware or build-time configuration + +**Performance tip:** Cache the redirects list in memory for 1-5 minutes to avoid fetching on every request. + +:::tip Integration with Webtools Router +This approach integrates seamlessly with the Webtools router workflow. See the [REST API Router documentation](/api/rest#router) for details on how to fetch content by path. +::: + +**No Cron Needed:** Unlike the [sitemap addon](/addons/sitemap/configuration/cron) which uses cron jobs to generate files, redirects are immediately available via the API after creation in the admin panel. + ## Redirect Chains and Loops The Webtools Redirects addon includes built-in protection against redirect chains and loops, which can harm user experience and SEO. @@ -161,12 +205,3 @@ Solution: 3. Auto-generate creates: /current → /new 4. Result: /old → /new and /current → /new ✓ ``` - -## Access -After you've followed the steps above you can now access your redirects through the REST API of Strapi. It will be available at: - -http://localhost:1337/api/webtools/redirects. - -:::caution -You need to setup permissions for this endpoint to be accessible. See the [REST API documentation](/webtools/addons/redirects/api/rest#permissions) for details. -::: From defd31a00296e5174628c5640c60d40f3edcb2b8 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:08:02 +0100 Subject: [PATCH 13/29] Document admin panel permissions --- .../docs/docs/addons/redirects/api/rest.md | 2 + .../redirects/getting-started/permissions.md | 112 ++++++++++++++++++ .../sitemap/getting-started/permissions.md | 71 +++++++++++ .../docs/docs/getting-started/permissions.md | 54 ++++++++- packages/docs/sidebars.ts | 2 + 5 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 packages/docs/docs/addons/redirects/getting-started/permissions.md create mode 100644 packages/docs/docs/addons/sitemap/getting-started/permissions.md diff --git a/packages/docs/docs/addons/redirects/api/rest.md b/packages/docs/docs/addons/redirects/api/rest.md index aaf6a2f1..cc49e05a 100644 --- a/packages/docs/docs/addons/redirects/api/rest.md +++ b/packages/docs/docs/addons/redirects/api/rest.md @@ -21,6 +21,8 @@ Before you can use the redirects endpoint publicly, you need to configure the ** **Quick Setup in Settings > Users & Permissions > Roles > Public:** - `webtools-addon-redirects.redirect.find` + +For detailed permission configuration including admin panel access, see the [Permissions documentation](/webtools/addons/redirects/permissions). ::: diff --git a/packages/docs/docs/addons/redirects/getting-started/permissions.md b/packages/docs/docs/addons/redirects/getting-started/permissions.md new file mode 100644 index 00000000..4a2827d3 --- /dev/null +++ b/packages/docs/docs/addons/redirects/getting-started/permissions.md @@ -0,0 +1,112 @@ +--- +sidebar_label: 'Permissions' +displayed_sidebar: webtoolsRedirectsSidebar +slug: /addons/redirects/permissions +--- + +# 🔐 Permissions + +The Redirects addon requires proper permissions configuration for both public API access and admin panel management. + +--- + +## 1. Public API Permissions + +For your frontend to access the redirects API endpoint. + +### Configuration + +1. Go to **Strapi Admin → Settings → Users & Permissions plugin → Roles**. +2. Select the role (e.g., **Public** or **Authenticated**). +3. Under **Webtools-addon-redirects** section. +4. Check **Redirect: find**. +5. Click **Save**. + +### What it enables + +- Access to `GET /api/webtools/redirects` endpoint +- Required for: Frontend redirect implementation + +:::danger Required for Frontend +Without this permission, you'll get a **403 Forbidden** error when calling the redirects API from your frontend. +::: + +--- + +## 2. Admin Panel Permissions + +For admin users to manage redirects in the Strapi admin panel. + +### Configuration + +1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. +2. Choose the role (e.g., **Editor**, **Author**). +3. Scroll to **Webtools-addon-redirects** plugin section. +4. Enable the permissions needed for this role. +5. Click **Save**. + +### Available Permissions + +#### Access the overview page +- **What it does:** Allows access to the redirects list page +- **Use case:** View all configured redirects +- **Required for:** Seeing the redirects overview in Webtools +- **UI Location:** `/plugins/webtools/redirects` + +#### Create new redirects +- **What it does:** Shows the "Create" button and allows access to the create page +- **Use case:** Let editors add new redirect rules +- **Required for:** Creating redirects via `/plugins/webtools/redirects/new` + +#### Edit existing redirects +- **What it does:** Allows access to the edit page for individual redirects +- **Use case:** Let editors modify existing redirect rules +- **Required for:** Updating redirects via `/plugins/webtools/redirects/:id` + +#### Delete existing redirects +- **What it does:** Shows the delete button and allows deletion of redirects +- **Use case:** Let editors remove outdated redirects +- **Required for:** Removing redirects from the system + +### Permission Combinations + +**For Content Editors:** +- ✅ Access the overview page +- ✅ Create new redirects +- ✅ Edit existing redirects +- ❌ Delete existing redirects (prevent accidental deletions) + +**For Senior Editors:** +- ✅ All permissions + +**For Viewers (read-only):** +- ✅ Access the overview page only + +--- + +## 3. Super Admin Role + +:::info Automatic Access +The **Super Admin** role has all permissions enabled by default and cannot be modified. All configurations are in read-only mode. +::: + +The **Settings** button visible in the permissions UI is for configuring RBAC conditions on other roles, but has no effect on Super Admin permissions. + +--- + +## Testing Permissions + +### Test Public API Access +```bash +curl "http://localhost:1337/api/webtools/redirects" +``` + +### Test Admin Panel Access +1. Create a test user with the configured role +2. Log in as that user +3. Navigate to Webtools → Redirects +4. Verify you can see/create/edit/delete according to permissions + +:::tip +Restart Strapi after making permission changes and clear your browser cache if needed. +::: diff --git a/packages/docs/docs/addons/sitemap/getting-started/permissions.md b/packages/docs/docs/addons/sitemap/getting-started/permissions.md new file mode 100644 index 00000000..4c5c8f7c --- /dev/null +++ b/packages/docs/docs/addons/sitemap/getting-started/permissions.md @@ -0,0 +1,71 @@ +--- +sidebar_label: 'Permissions' +displayed_sidebar: webtoolsSitemapSidebar +slug: /addons/sitemap/permissions +--- + +# 🔐 Permissions + +The Sitemap addon has minimal permission requirements since it's primarily a read-only feature. + +--- + +## Admin Panel Permission + +### Configuration + +1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. +2. Choose the role (e.g., **Editor**, **Author**). +3. Under **Webtools-addon-sitemap** plugin section. +4. Enable **Access the plugin settings**. +5. Click **Save**. + +### Access the plugin settings + +- **What it does:** Allows access to the sitemap settings page +- **Use case:** View sitemap configuration and regenerate sitemaps +- **Required for:** Accessing `/plugins/webtools/sitemap` +- **Capabilities:** + - View sitemap settings (hostname, exclude drafts, etc.) + - See sitemap generation status + - Manually regenerate sitemaps + - View sitemap URLs + +:::info Read-Only Access +The sitemap addon provides primarily read-only access. Configuration changes are made in `config/plugins.js` and require developer/system admin access. +::: + +--- + +## Public Access + +The sitemap XML files are publicly accessible by default: + +- `/sitemap.xml` - Main sitemap or sitemap index +- `/sitemap/[name].xml` - Individual sitemaps + +**No permission configuration needed** - these endpoints are automatically enabled during bootstrap for the Public role. + +--- + +## Super Admin Role + +:::info Automatic Access +The **Super Admin** role has all permissions enabled by default and cannot be modified. +::: + +--- + +## Testing Permissions + +### Test Admin Panel Access +1. Log in with a user that has the "Access the plugin settings" permission +2. Navigate to Webtools → Sitemap +3. Verify you can view settings and regenerate sitemaps + +### Test Public Sitemap Access +```bash +curl "http://localhost:1337/sitemap.xml" +``` + +The sitemap should be accessible without authentication. diff --git a/packages/docs/docs/getting-started/permissions.md b/packages/docs/docs/getting-started/permissions.md index 15e3d3b9..7e470159 100644 --- a/packages/docs/docs/getting-started/permissions.md +++ b/packages/docs/docs/getting-started/permissions.md @@ -46,18 +46,60 @@ Enable the Webtools endpoints for your front-end: ## 3. Admin Panel roles -Want your editors/admins to manage Webtools settings? Configure: +Want your editors/admins to manage Webtools settings? Configure admin panel permissions: + +### How to Configure 1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. -2. Choose the role (e.g., **Author**). -3. Under **Plugins** → **Webtools** enable the permissions you need: - - **Access the URL alias list** - - **Access the URL alias patterns** - - **Access the URL alias sidebar** +2. Choose the role (e.g., **Author**, **Editor**). +3. Under **Plugins** → **Webtools** enable the permissions you need. 4. Click **Save**. Admin Panel Webtools access rights +### Available Permissions + +#### Access the overview page +- **What it does:** Allows access to the main Webtools overview page at `/plugins/webtools` +- **Use case:** Give users a dashboard view of all Webtools features +- **Required for:** Viewing the Webtools main navigation and overview + +#### Access the URL alias list +- **What it does:** Allows access to the URL Aliases list page +- **Use case:** Let editors view and manage all URL aliases created for content +- **Required for:** Viewing the list of all generated URLs + +#### Access the URL alias patterns +- **What it does:** Allows access to the URL Patterns management pages (list, create, edit) +- **Use case:** Give admins ability to configure URL pattern templates +- **Required for:** Managing URL generation rules (e.g., `/blog/[title]`) + +#### Access the URL alias sidebar +- **What it does:** Shows/hides the Webtools panel in the Content Manager sidebar +- **Use case:** Let content editors see and manage URLs when editing content +- **Required for:** Viewing URL information in the Content Manager + +### Permission Combinations + +**For Content Editors:** +- ✅ Access the URL alias sidebar (to see URLs when editing) +- ✅ Access the URL alias list (to view all URLs) +- ❌ Access the URL alias patterns (prevent pattern changes) +- ❌ Access the overview page (optional) + +**For Admins:** +- ✅ All permissions (full access) + +### Notes + +:::info Super Admin +The **Super Admin** role has all permissions enabled by default and cannot be modified. The Settings button visible in the permissions UI allows adding RBAC conditions for other roles, but is read-only for Super Admin. +::: + +:::tip RBAC Conditions +For non-Super-Admin roles, you can click the **Settings** button next to permissions to add conditional access rules (e.g., "can edit when user is creator"). See [Strapi RBAC documentation](https://docs.strapi.io/dev-docs/configurations/rbac) for details. +::: + --- ## Test your permissions diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index fd65905e..5d08ab6d 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -117,6 +117,7 @@ const sidebars = { "addons/sitemap/getting-started/sitemap-index", "addons/sitemap/getting-started/robots-txt", "addons/sitemap/getting-started/cli", + "addons/sitemap/getting-started/permissions", ], }, { @@ -167,6 +168,7 @@ const sidebars = { "addons/redirects/getting-started/introduction", "addons/redirects/getting-started/installation", "addons/redirects/getting-started/usage", + "addons/redirects/getting-started/permissions", ], }, { From 36d869cc77477cf624b0852afda86c5cdab14cb5 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:30:06 +0100 Subject: [PATCH 14/29] rename files to light-dark mode --- ...add_new_pattern.png => add_new_pattern-dark.png} | Bin .../links/{ckeditor.png => ckeditor-light.png} | Bin ...link-modal.png => ckeditor-link-modal-light.png} | Bin ...{link-component.png => link-component-light.png} | Bin ...custom-field.png => link-custom-field-light.png} | Bin ...ng => webtools-pro-link-addon-options-light.png} | Bin ...ate-redirects.png => create-redirects-light.png} | Bin ...ts-overview.png => redirects-overview-light.png} | Bin .../{URL-bundle.png => URL-bundle-light.png} | Bin .../{custom-url.png => custom-url-light.png} | Bin .../sitemap/{settings.png => settings-light.png} | Bin ...nable-webtools.png => enable-webtools-light.png} | Bin ...n-roles.png => permissions-admin-roles-dark.png} | Bin ...ons-ct-find.png => permissions-ct-find-dark.png} | Bin ...-find.png => permissions-webtools-find-dark.png} | Bin .../assets/{url-alias.png => url-alias-light.png} | Bin .../{url_patterns.png => url_patterns-dark.png} | Bin 17 files changed, 0 insertions(+), 0 deletions(-) rename packages/docs/static/img/assets/{add_new_pattern.png => add_new_pattern-dark.png} (100%) rename packages/docs/static/img/assets/addons/links/{ckeditor.png => ckeditor-light.png} (100%) rename packages/docs/static/img/assets/addons/links/{ckeditor-link-modal.png => ckeditor-link-modal-light.png} (100%) rename packages/docs/static/img/assets/addons/links/{link-component.png => link-component-light.png} (100%) rename packages/docs/static/img/assets/addons/links/{link-custom-field.png => link-custom-field-light.png} (100%) rename packages/docs/static/img/assets/addons/links/{webtools-pro-link-addon-options.png => webtools-pro-link-addon-options-light.png} (100%) rename packages/docs/static/img/assets/addons/redirects/{create-redirects.png => create-redirects-light.png} (100%) rename packages/docs/static/img/assets/addons/redirects/{redirects-overview.png => redirects-overview-light.png} (100%) rename packages/docs/static/img/assets/addons/sitemap/{URL-bundle.png => URL-bundle-light.png} (100%) rename packages/docs/static/img/assets/addons/sitemap/{custom-url.png => custom-url-light.png} (100%) rename packages/docs/static/img/assets/addons/sitemap/{settings.png => settings-light.png} (100%) rename packages/docs/static/img/assets/{enable-webtools.png => enable-webtools-light.png} (100%) rename packages/docs/static/img/assets/{permissions-admin-roles.png => permissions-admin-roles-dark.png} (100%) rename packages/docs/static/img/assets/{permissions-ct-find.png => permissions-ct-find-dark.png} (100%) rename packages/docs/static/img/assets/{permissions-webtools-find.png => permissions-webtools-find-dark.png} (100%) rename packages/docs/static/img/assets/{url-alias.png => url-alias-light.png} (100%) rename packages/docs/static/img/assets/{url_patterns.png => url_patterns-dark.png} (100%) diff --git a/packages/docs/static/img/assets/add_new_pattern.png b/packages/docs/static/img/assets/add_new_pattern-dark.png similarity index 100% rename from packages/docs/static/img/assets/add_new_pattern.png rename to packages/docs/static/img/assets/add_new_pattern-dark.png diff --git a/packages/docs/static/img/assets/addons/links/ckeditor.png b/packages/docs/static/img/assets/addons/links/ckeditor-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/links/ckeditor.png rename to packages/docs/static/img/assets/addons/links/ckeditor-light.png diff --git a/packages/docs/static/img/assets/addons/links/ckeditor-link-modal.png b/packages/docs/static/img/assets/addons/links/ckeditor-link-modal-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/links/ckeditor-link-modal.png rename to packages/docs/static/img/assets/addons/links/ckeditor-link-modal-light.png diff --git a/packages/docs/static/img/assets/addons/links/link-component.png b/packages/docs/static/img/assets/addons/links/link-component-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/links/link-component.png rename to packages/docs/static/img/assets/addons/links/link-component-light.png diff --git a/packages/docs/static/img/assets/addons/links/link-custom-field.png b/packages/docs/static/img/assets/addons/links/link-custom-field-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/links/link-custom-field.png rename to packages/docs/static/img/assets/addons/links/link-custom-field-light.png diff --git a/packages/docs/static/img/assets/addons/links/webtools-pro-link-addon-options.png b/packages/docs/static/img/assets/addons/links/webtools-pro-link-addon-options-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/links/webtools-pro-link-addon-options.png rename to packages/docs/static/img/assets/addons/links/webtools-pro-link-addon-options-light.png diff --git a/packages/docs/static/img/assets/addons/redirects/create-redirects.png b/packages/docs/static/img/assets/addons/redirects/create-redirects-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/redirects/create-redirects.png rename to packages/docs/static/img/assets/addons/redirects/create-redirects-light.png diff --git a/packages/docs/static/img/assets/addons/redirects/redirects-overview.png b/packages/docs/static/img/assets/addons/redirects/redirects-overview-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/redirects/redirects-overview.png rename to packages/docs/static/img/assets/addons/redirects/redirects-overview-light.png diff --git a/packages/docs/static/img/assets/addons/sitemap/URL-bundle.png b/packages/docs/static/img/assets/addons/sitemap/URL-bundle-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/sitemap/URL-bundle.png rename to packages/docs/static/img/assets/addons/sitemap/URL-bundle-light.png diff --git a/packages/docs/static/img/assets/addons/sitemap/custom-url.png b/packages/docs/static/img/assets/addons/sitemap/custom-url-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/sitemap/custom-url.png rename to packages/docs/static/img/assets/addons/sitemap/custom-url-light.png diff --git a/packages/docs/static/img/assets/addons/sitemap/settings.png b/packages/docs/static/img/assets/addons/sitemap/settings-light.png similarity index 100% rename from packages/docs/static/img/assets/addons/sitemap/settings.png rename to packages/docs/static/img/assets/addons/sitemap/settings-light.png diff --git a/packages/docs/static/img/assets/enable-webtools.png b/packages/docs/static/img/assets/enable-webtools-light.png similarity index 100% rename from packages/docs/static/img/assets/enable-webtools.png rename to packages/docs/static/img/assets/enable-webtools-light.png diff --git a/packages/docs/static/img/assets/permissions-admin-roles.png b/packages/docs/static/img/assets/permissions-admin-roles-dark.png similarity index 100% rename from packages/docs/static/img/assets/permissions-admin-roles.png rename to packages/docs/static/img/assets/permissions-admin-roles-dark.png diff --git a/packages/docs/static/img/assets/permissions-ct-find.png b/packages/docs/static/img/assets/permissions-ct-find-dark.png similarity index 100% rename from packages/docs/static/img/assets/permissions-ct-find.png rename to packages/docs/static/img/assets/permissions-ct-find-dark.png diff --git a/packages/docs/static/img/assets/permissions-webtools-find.png b/packages/docs/static/img/assets/permissions-webtools-find-dark.png similarity index 100% rename from packages/docs/static/img/assets/permissions-webtools-find.png rename to packages/docs/static/img/assets/permissions-webtools-find-dark.png diff --git a/packages/docs/static/img/assets/url-alias.png b/packages/docs/static/img/assets/url-alias-light.png similarity index 100% rename from packages/docs/static/img/assets/url-alias.png rename to packages/docs/static/img/assets/url-alias-light.png diff --git a/packages/docs/static/img/assets/url_patterns.png b/packages/docs/static/img/assets/url_patterns-dark.png similarity index 100% rename from packages/docs/static/img/assets/url_patterns.png rename to packages/docs/static/img/assets/url_patterns-dark.png From 9a22eda00c69104f1588a7d3a22d7825f41fb01a Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:45:28 +0100 Subject: [PATCH 15/29] Convert screenshots to ThemedImage with light/dark support --- .../addons/links/getting-started/ckeditor.md | 21 ++++++++++++--- .../links/getting-started/custom-field.md | 16 +++++++++-- .../addons/redirects/getting-started/usage.md | 19 +++++++++++-- .../addons/sitemap/getting-started/usage.md | 19 +++++++++++-- .../addons/sitemap/settings/introduction.md | 11 +++++++- .../docs/docs/getting-started/permissions.md | 27 ++++++++++++++++--- .../docs/docs/getting-started/url-alias.md | 11 +++++++- .../docs/docs/getting-started/url-pattern.md | 19 +++++++++++-- packages/docs/docs/getting-started/usage.md | 11 +++++++- 9 files changed, 137 insertions(+), 17 deletions(-) diff --git a/packages/docs/docs/addons/links/getting-started/ckeditor.md b/packages/docs/docs/addons/links/getting-started/ckeditor.md index f59a8b04..95a4dba0 100644 --- a/packages/docs/docs/addons/links/getting-started/ckeditor.md +++ b/packages/docs/docs/addons/links/getting-started/ckeditor.md @@ -4,11 +4,26 @@ displayed_sidebar: webtoolsLinksSidebar slug: /addons/links/ckeditor --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # Ckeditor integration -This addon has an integration with [the Ckeditor plugin](https://github.com/nshenderov/strapi-plugin-ckeditor). If the Ckeditor plugin is installed this addon will replace the link button in the editor. With this new button you can create internal links in the ckeditor. +This addon has an integration with [the Ckeditor plugin](https://github.com/nshenderov/strapi-plugin-ckeditor). If the Ckeditor plugin is installed this addon will replace the link button in the editor. With this new button you can create internal links in the ckeditor. -Ckeditor + If you click the link button it will open a modal in which you can manage your links. -Ckeditor link modal + diff --git a/packages/docs/docs/addons/links/getting-started/custom-field.md b/packages/docs/docs/addons/links/getting-started/custom-field.md index 936973de..e830d450 100644 --- a/packages/docs/docs/addons/links/getting-started/custom-field.md +++ b/packages/docs/docs/addons/links/getting-started/custom-field.md @@ -7,11 +7,23 @@ slug: /addons/links/custom-field # Custom field This addon introduces a new custom field which you can add to your content types. This field can be used in your content types to accommodate internal linking from one page to another. -Link custom field + ### This custom field will provide you three options in the advanced settings: * Set the link to "internal" and now you can search on something like "My first blog post". The field stores a documentId reference, so the link keeps working even if the slug or URL changes. * Set the link to "external" so you can enter a full url, e.g. https://strapi.io/ * Set the link to "Internal & external links" and have both link options as described above, this is the default value. -Link advanced settings + diff --git a/packages/docs/docs/addons/redirects/getting-started/usage.md b/packages/docs/docs/addons/redirects/getting-started/usage.md index 5921a643..8b2712e2 100644 --- a/packages/docs/docs/addons/redirects/getting-started/usage.md +++ b/packages/docs/docs/addons/redirects/getting-started/usage.md @@ -4,6 +4,9 @@ displayed_sidebar: webtoolsRedirectsSidebar slug: /addons/redirects/usage --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 💡 Usage With this plugin you have full control over which redirects should be active for your front-end. You can create, update and delete redirects right from the Strapi admin panel. @@ -11,13 +14,25 @@ With this plugin you have full control over which redirects should be active for On the redirects overview you can see all the redirects on your site. -Redirects overview + ## Create redirects With the button in the top right you can create new redirects. -Create redirects + ### URL Format diff --git a/packages/docs/docs/addons/sitemap/getting-started/usage.md b/packages/docs/docs/addons/sitemap/getting-started/usage.md index a6b1050e..44128440 100644 --- a/packages/docs/docs/addons/sitemap/getting-started/usage.md +++ b/packages/docs/docs/addons/sitemap/getting-started/usage.md @@ -4,6 +4,9 @@ displayed_sidebar: webtoolsSitemapSidebar slug: /addons/sitemap/usage --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 💡 Usage With this plugin you have full control over which URLs you add to your sitemap XML. Go to the admin section of the plugin and start adding URLs. Here you will find that there are two ways to add URLs to the sitemap. With **URL bundles** and **Custom URLs**. @@ -21,7 +24,13 @@ URLs coming from a URL bundle will get the following XML attributes: - `` - `` -URL bundle + ## Custom URLs A custom URL is meant to add URLs to the sitemap which are not managed in Strapi. It might be that you have custom route like `/account` that is hardcoded in your front-end. If you'd want to add such a route (URL) to the sitemap you can add it as a custom URL. @@ -32,7 +41,13 @@ Custom URLs will get the following XML attributes: - `` - `` -Custom URL + ## Generate After you've successfully configured your sitemap it's time to generate it. You can generate the sitemap manually by clicking the 'Generate sitemap' button in the admin panel. diff --git a/packages/docs/docs/addons/sitemap/settings/introduction.md b/packages/docs/docs/addons/sitemap/settings/introduction.md index a5811ab0..88978c8c 100644 --- a/packages/docs/docs/addons/sitemap/settings/introduction.md +++ b/packages/docs/docs/addons/sitemap/settings/introduction.md @@ -4,7 +4,16 @@ displayed_sidebar: webtoolsSitemapSidebar slug: /addons/sitemap/settings --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # Settings Settings can be changed in the admin section of the plugin. In the last tab (Settings) you will find the settings as described below. -Sitemap settings + diff --git a/packages/docs/docs/getting-started/permissions.md b/packages/docs/docs/getting-started/permissions.md index 7e470159..5ff69791 100644 --- a/packages/docs/docs/getting-started/permissions.md +++ b/packages/docs/docs/getting-started/permissions.md @@ -4,6 +4,9 @@ displayed_sidebar: webtoolsSidebar slug: /permissions --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 🔐 Role-Based Access Control (RBAC) After installation, review Webtools permissions per role in Settings so your front-end can access the required endpoints. @@ -26,7 +29,13 @@ For each content-type where you've enabled Webtools, you need to open up the sta 4. Check **Find** (and **Find One** if desired). 5. Click **Save**. -Content Type Find permissions + --- @@ -40,7 +49,13 @@ Enable the Webtools endpoints for your front-end: - **URL Alias: find** 3. Click **Save**. -Webtools Router & URL Alias find permissions + --- @@ -55,7 +70,13 @@ Want your editors/admins to manage Webtools settings? Configure admin panel perm 3. Under **Plugins** → **Webtools** enable the permissions you need. 4. Click **Save**. -Admin Panel Webtools access rights + ### Available Permissions diff --git a/packages/docs/docs/getting-started/url-alias.md b/packages/docs/docs/getting-started/url-alias.md index daa01be1..0643270f 100644 --- a/packages/docs/docs/getting-started/url-alias.md +++ b/packages/docs/docs/getting-started/url-alias.md @@ -4,9 +4,18 @@ displayed_sidebar: webtoolsSidebar slug: /url-alias --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 💡 URL alias At the core of the plugin is URL alias. It's the idea that every page of a given collection type represents a page in your website frontend. Each of those pages will have a unique URL path which can be altered on the backend. Then all those URL paths can be used in your frontend to setup dynamic routing. See below a screenshot of the URL alias popup that's used to set the unique path of your page. -URL alias + diff --git a/packages/docs/docs/getting-started/url-pattern.md b/packages/docs/docs/getting-started/url-pattern.md index 49eef7d7..7155f4ab 100644 --- a/packages/docs/docs/getting-started/url-pattern.md +++ b/packages/docs/docs/getting-started/url-pattern.md @@ -4,12 +4,21 @@ displayed_sidebar: webtoolsSidebar slug: /url-pattern --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 🔌 URL pattern To create dynamic URLs this plugin uses **URL patterns**. The URL pattern will be used to generate unique URLs based on the data available. You can add URL patterns in the settings section of the plugin. For configuration details and fallbacks, see [Default pattern](/webtools/configuration/default-pattern) and [Slugify](/webtools/configuration/slugify). -URL patterns overview + ``` /pages/[my-title-field] @@ -29,4 +38,10 @@ The following field types are allowed in a pattern: See below a screenshot of the URL pattern creation form in Strapi. -Add new pattern with field suggestions + diff --git a/packages/docs/docs/getting-started/usage.md b/packages/docs/docs/getting-started/usage.md index 6514e869..51340fa0 100644 --- a/packages/docs/docs/getting-started/usage.md +++ b/packages/docs/docs/getting-started/usage.md @@ -4,6 +4,9 @@ displayed_sidebar: webtoolsSidebar slug: /usage --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # 💡 Usage This plugin is specifically designed for usage in Strapi managed websites. Hence the name **web**tools. The plugin offers a variety of functionalities which you'll have to manually enable. @@ -20,7 +23,13 @@ Once you enable Webtools for a content-type each entry of that type will get it' See below a screenshot of how to enable webtools for a given collection type. -Enable webtools + ### Using the CLI From 74183e16c3fe90e7e79000204b95b09d96c3f778 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 10 Nov 2025 20:49:11 +0100 Subject: [PATCH 16/29] Changed two photos to themed way of showing --- .../docs/docs/getting-started/url-alias.md | 2 +- packages/docs/docs/getting-started/usage.md | 2 +- .../static/img/assets/enable-webtools-dark.png | Bin 0 -> 102900 bytes .../docs/static/img/assets/url-alias-dark.png | Bin 0 -> 77359 bytes 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 packages/docs/static/img/assets/enable-webtools-dark.png create mode 100644 packages/docs/static/img/assets/url-alias-dark.png diff --git a/packages/docs/docs/getting-started/url-alias.md b/packages/docs/docs/getting-started/url-alias.md index 0643270f..cc630e8a 100644 --- a/packages/docs/docs/getting-started/url-alias.md +++ b/packages/docs/docs/getting-started/url-alias.md @@ -16,6 +16,6 @@ See below a screenshot of the URL alias popup that's used to set the unique path alt="URL alias" sources={{ light: useBaseUrl('/webtools/img/assets/url-alias-light.png'), - dark: useBaseUrl('/webtools/img/assets/url-alias-light.png'), + dark: useBaseUrl('/webtools/img/assets/url-alias-dark.png'), }} /> diff --git a/packages/docs/docs/getting-started/usage.md b/packages/docs/docs/getting-started/usage.md index 51340fa0..aef3ab38 100644 --- a/packages/docs/docs/getting-started/usage.md +++ b/packages/docs/docs/getting-started/usage.md @@ -27,7 +27,7 @@ See below a screenshot of how to enable webtools for a given collection type. alt="Enable webtools" sources={{ light: useBaseUrl('/webtools/img/assets/enable-webtools-light.png'), - dark: useBaseUrl('/webtools/img/assets/enable-webtools-light.png'), + dark: useBaseUrl('/webtools/img/assets/enable-webtools-dark.png'), }} /> diff --git a/packages/docs/static/img/assets/enable-webtools-dark.png b/packages/docs/static/img/assets/enable-webtools-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e38511b3a39818986a501a36514488708f526638 GIT binary patch literal 102900 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 literal 0 HcmV?d00001 diff --git a/packages/docs/static/img/assets/url-alias-dark.png b/packages/docs/static/img/assets/url-alias-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9841a0f437264c76770237ddc5057f54b51dbd GIT binary patch literal 77359 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

VK73~Kw0=Iy#^&@Zxrt}0 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 z zcGdKlUF`{B@3k*>`@0MU6q66?`gL6M?bzF=;g(T)zeZNGiuo^m0vg;WME0J8`R-f=t+A#h$p;}Z@GI}w*pw^~NODb*o zMFBct_c-R`d52h0Yinz#>D~^>Tt$+~{CT$`c-BXzuUz8=fn^ z(YWa>G>Ib%_JcMVkB%5U2#{LD8y+uqZeaw0&M2En6HJ1AYC;&%6=QtwM{xWp!cnll zpZKW4cp68lNln_oOWfP$VS$P?oePY}YD;Y!RyL<_;n6ViA`=yiYhEM8SgI7uZN*!X z4u0a7g#PQgOk@IjUDKA52qKsfPN(4n3DHemB#7FYmlx2H8d{;^U>+!PcF zSqx3M^7HC8(K_PxW|qN;;C}L-2KitC26-@Pre(zMLsSr4x-&y@W$OE9b zG%g2LALN7M-+2FS4Hx9{)A0MjROAWi_pXpC|EMqRSvDnb&MbbN$CbUILWd z^)bcs0iR9&zWiKc0R8$aNf17o>@VH6OBQ54b7%cd{^PFcgT(A)$)|EYYWA;T-4wte uM*cZ?eu;zci~awj@i#-_|LSOPg=uY8I)}wSp7;s;Oir8qQS`gR-TwlFpGlwq literal 0 HcmV?d00001 From 11a074fffa465f55cc79312a723a0d793b642070 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:03:12 +0100 Subject: [PATCH 17/29] Fix Linting Error + updated caniuse-db --- .../docs/docs/addons/links/getting-started/custom-field.md | 3 +++ yarn.lock | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/docs/docs/addons/links/getting-started/custom-field.md b/packages/docs/docs/addons/links/getting-started/custom-field.md index e830d450..18041586 100644 --- a/packages/docs/docs/addons/links/getting-started/custom-field.md +++ b/packages/docs/docs/addons/links/getting-started/custom-field.md @@ -4,6 +4,9 @@ displayed_sidebar: webtoolsLinksSidebar slug: /addons/links/custom-field --- +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + # Custom field This addon introduces a new custom field which you can add to your content types. This field can be used in your content types to accommodate internal linking from one page to another. diff --git a/yarn.lock b/yarn.lock index 6b008e33..fb65f6ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11814,9 +11814,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702": - version: 1.0.30001713 - resolution: "caniuse-lite@npm:1.0.30001713" - checksum: 10c0/f5468abfe73ce30e29cc8bde2ea67df2aab69032bdd93345e0640efefb76b7901c84fe1d28d591a797e65fe52fc24cae97060bb5552f9f9740322aff95ce2f9d + version: 1.0.30001754 + resolution: "caniuse-lite@npm:1.0.30001754" + checksum: 10c0/d38709ab11abc36eea28068d241434eba925c4d3462916ccaa17a34a6227dfdeb58ab0e1eb614bab12fb393c7d527db392a0f477b48c33d70d8e466954f381ba languageName: node linkType: hard From f8dada16021f68e7fa8e03010cda9d62bb673551 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:05:27 +0100 Subject: [PATCH 18/29] Add changeset --- .changeset/hot-grapes-allow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hot-grapes-allow.md diff --git a/.changeset/hot-grapes-allow.md b/.changeset/hot-grapes-allow.md new file mode 100644 index 00000000..b89d7046 --- /dev/null +++ b/.changeset/hot-grapes-allow.md @@ -0,0 +1,5 @@ +--- +"docs": patch +--- + +Chore/documentation quality From b218bd3baee0775dae8018e55d18b20a09c5ef0b Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 15:36:18 +0100 Subject: [PATCH 19/29] Split permissions in admin and api permissions + added API token docs --- .../getting-started/admin-permissions.md | 143 ++++++++++++++ .../getting-started/api-permissions.md | 181 ++++++++++++++++++ .../redirects/getting-started/permissions.md | 112 ----------- packages/docs/sidebars.ts | 3 +- 4 files changed, 326 insertions(+), 113 deletions(-) create mode 100644 packages/docs/docs/addons/redirects/getting-started/admin-permissions.md create mode 100644 packages/docs/docs/addons/redirects/getting-started/api-permissions.md delete mode 100644 packages/docs/docs/addons/redirects/getting-started/permissions.md diff --git a/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md b/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md new file mode 100644 index 00000000..ee800b62 --- /dev/null +++ b/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md @@ -0,0 +1,143 @@ +--- +sidebar_label: 'Admin Permissions' +displayed_sidebar: webtoolsRedirectsSidebar +slug: /addons/redirects/admin-permissions +--- + +# 🔐 Admin Panel Permissions + +The Redirects addon provides granular permissions for controlling what admin users can do in the Strapi admin panel. + +--- + +## Setting up Admin Panel Permissions + +For admin users to manage redirects in the Strapi admin panel. + +### Configuration Steps + +1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. +2. Choose the role (e.g., **Editor**, **Author**). +3. Scroll to **Webtools-addon-redirects** plugin section. +4. Enable the permissions needed for this role. +5. Click **Save**. + +--- + +## Available Permissions + +### Access the overview page +- **What it does:** Allows access to the redirects list page +- **Use case:** View all configured redirects +- **Required for:** Seeing the redirects overview in Webtools +- **UI Location:** `/plugins/webtools/redirects` + +### Create new redirects +- **What it does:** Shows the "Create" button and allows access to the create page +- **Use case:** Let editors add new redirect rules +- **Required for:** Creating redirects via `/plugins/webtools/redirects/new` + +### Edit existing redirects +- **What it does:** Allows access to the edit page for individual redirects +- **Use case:** Let editors modify existing redirect rules +- **Required for:** Updating redirects via `/plugins/webtools/redirects/:id` + +### Delete existing redirects +- **What it does:** Shows the delete button and allows deletion of redirects +- **Use case:** Let editors remove outdated redirects +- **Required for:** Removing redirects from the system + +--- + +## Permission Combinations + +Here are some common permission setups based on different roles: + +### For Content Editors +- ✅ Access the overview page +- ✅ Create new redirects +- ✅ Edit existing redirects +- ❌ Delete existing redirects (prevent accidental deletions) + +**Use case:** Content editors who need to manage redirects but shouldn't be able to delete them without approval. + +### For Senior Editors +- ✅ All permissions + +**Use case:** Trusted users who can fully manage redirects including deletions. + +### For Viewers (read-only) +- ✅ Access the overview page only + +**Use case:** Stakeholders or reviewers who need to see redirects but not modify them. + +--- + +## Super Admin Role + +:::info Automatic Access +The **Super Admin** role has all permissions enabled by default and cannot be modified. All configurations are in read-only mode. +::: + +The **Settings** button visible in the permissions UI is for configuring RBAC conditions on other roles, but has no effect on Super Admin permissions. + +--- + +## Testing Admin Panel Access + +### Test Workflow + +1. Create a test user with the configured role +2. Log in as that user +3. Navigate to **Webtools → Redirects** +4. Verify you can see/create/edit/delete according to permissions + +### Expected Behavior + +**With "Access the overview page" only:** +- Can see the redirects list +- No "Create" button visible +- Cannot access edit or delete actions + +**With all permissions:** +- Can see the redirects list +- "Create" button is visible +- Can click on redirects to edit +- Delete button/action is available + +:::tip +Restart Strapi after making permission changes and clear your browser cache if needed. +::: + +--- + +## Troubleshooting + +### User cannot access Webtools plugin + +**Problem:** The Webtools menu item is not visible in the sidebar. + +**Solutions:** +- Verify the user has at least "Access the overview page" permission +- Check that the user's role is not disabled +- Log out and log back in +- Clear browser cache + +### Create/Edit/Delete buttons not showing + +**Problem:** User can see redirects but action buttons are missing. + +**Solutions:** +- Verify the specific permissions (create/edit/delete) are enabled for the user's role +- Refresh the page after permission changes +- Check browser console for permission errors + +### Permission changes not taking effect + +**Problem:** After updating permissions, user still has old access level. + +**Solutions:** +- Ask the user to log out and log back in +- Restart Strapi server +- Clear browser cache and cookies +- Verify you clicked "Save" after changing permissions diff --git a/packages/docs/docs/addons/redirects/getting-started/api-permissions.md b/packages/docs/docs/addons/redirects/getting-started/api-permissions.md new file mode 100644 index 00000000..d311c816 --- /dev/null +++ b/packages/docs/docs/addons/redirects/getting-started/api-permissions.md @@ -0,0 +1,181 @@ +--- +sidebar_label: 'API Permissions' +displayed_sidebar: webtoolsRedirectsSidebar +slug: /addons/redirects/api-permissions +--- + +# 🔐 API Permissions + +The Redirects addon exposes a public API endpoint that your frontend can use to fetch redirect rules. This requires proper permissions configuration. + +--- + +## Setting up Public API Access + +For your frontend application to access the redirects API endpoint. + +### Configuration Steps + +1. Go to **Strapi Admin → Settings → Users & Permissions plugin → Roles**. +2. Select the role (e.g., **Public** or **Authenticated**). +3. Under **Webtools-addon-redirects** section. +4. Check **Redirect: find**. +5. Click **Save**. + +### What it enables + +- Access to `GET /api/webtools/redirects` endpoint +- Required for: Frontend redirect implementation + +:::danger Required for Frontend +Without this permission, you'll get a **403 Forbidden** error when calling the redirects API from your frontend. +::: + +--- + +## Access via API Tokens + +In addition to the Users & Permissions plugin (for public and authenticated users), you can also use **API Tokens** for programmatic access to the redirects endpoint. + +### When to use API Tokens + +- **Build-time data fetching**: Static site generators (Next.js, Gatsby, etc.) +- **Server-to-server communication**: Backend services fetching redirect rules +- **CI/CD pipelines**: Automated testing or validation of redirects +- **Webhook handlers**: External services that need to check redirects + +### Creating an API Token + +1. Go to **Strapi Admin → Settings → API Tokens**. +2. Click **Create new API Token**. +3. Configure the token: + - **Name**: e.g., "Frontend Build Token" or "Redirects API Access" + - **Description**: Optional description of the token's purpose + - **Token duration**: Unlimited, 7 days, 30 days, or 90 days + - **Token type**: Choose based on your needs: + - **Read-only**: Can only fetch data (recommended for redirects) + - **Full access**: Can create, update, and delete (use with caution) + - **Custom**: Fine-grained permissions (see below) + +4. Click **Save** and copy the generated token immediately (it won't be shown again). + +### Configuring Custom Permissions for API Tokens + +For better security, use **Custom** token type with specific permissions: + +1. Select **Custom** as Token type. +2. Scroll to **Webtools-addon-redirects** section. +3. Enable only the permissions needed: + - **find**: Allows `GET /api/webtools/redirects` (✅ recommended) + - **findOne**: Allows fetching a single redirect by ID + - **create**, **update**, **delete**: Only enable if programmatic management is needed + +:::tip Security Best Practice +Use **Read-only** tokens or **Custom** tokens with only `find` permission enabled for frontend applications. Never expose tokens with write permissions in client-side code. +::: + +### Using the API Token + +Include the token in the `Authorization` header when making requests: + +```bash +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/api/webtools/redirects" +``` + +**Next.js example (server-side):** +```javascript +// app/[[...slug]]/page.tsx or pages/[[...slug]].tsx +export async function generateStaticParams() { + const response = await fetch('https://your-strapi.com/api/webtools/redirects', { + headers: { + 'Authorization': `Bearer ${process.env.STRAPI_API_TOKEN}`, + }, + }); + const redirects = await response.json(); + // Process redirects... +} +``` + +**Important:** Store API tokens in environment variables (`.env.local`), never commit them to version control. + +--- + +## Testing API Access + +### Test with Public/Authenticated role +```bash +# Without authentication (requires Public role permissions) +curl "http://localhost:1337/api/webtools/redirects" + +# With user JWT token (requires Authenticated role permissions) +curl -H "Authorization: Bearer USER_JWT_TOKEN" \ + "http://localhost:1337/api/webtools/redirects" +``` + +### Test with API Token +```bash +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/api/webtools/redirects" +``` + +**Expected response:** +```json +{ + "data": [ + { + "id": 1, + "source": "/old-page", + "destination": "/new-page", + "statusCode": 301, + // ... + } + ] +} +``` + +:::tip +After making permission changes, restart Strapi and clear your browser cache if needed. +::: + +--- + +## Troubleshooting + +### 403 Forbidden Error + +**Problem:** Getting 403 when calling the API endpoint. + +**Solutions:** +- Verify the correct role (Public/Authenticated) has `find` permission enabled +- If using API token, verify it's valid and has correct permissions +- Restart Strapi after permission changes +- Check that the token hasn't expired + +### API Token not working + +**Problem:** Valid token returns 401 Unauthorized. + +**Solutions:** +- Ensure token is included in `Authorization: Bearer TOKEN` header +- Verify token hasn't expired +- Check token type has necessary permissions (not Read-only for write operations) +- Regenerate token if needed + +### CORS issues in frontend + +**Problem:** Browser blocks API requests. + +**Solutions:** +- Configure CORS in `config/middlewares.js`: +```javascript +module.exports = [ + // ... + { + name: 'strapi::cors', + config: { + origin: ['http://localhost:3000', 'https://your-frontend.com'], + }, + }, +]; +``` diff --git a/packages/docs/docs/addons/redirects/getting-started/permissions.md b/packages/docs/docs/addons/redirects/getting-started/permissions.md deleted file mode 100644 index 4a2827d3..00000000 --- a/packages/docs/docs/addons/redirects/getting-started/permissions.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -sidebar_label: 'Permissions' -displayed_sidebar: webtoolsRedirectsSidebar -slug: /addons/redirects/permissions ---- - -# 🔐 Permissions - -The Redirects addon requires proper permissions configuration for both public API access and admin panel management. - ---- - -## 1. Public API Permissions - -For your frontend to access the redirects API endpoint. - -### Configuration - -1. Go to **Strapi Admin → Settings → Users & Permissions plugin → Roles**. -2. Select the role (e.g., **Public** or **Authenticated**). -3. Under **Webtools-addon-redirects** section. -4. Check **Redirect: find**. -5. Click **Save**. - -### What it enables - -- Access to `GET /api/webtools/redirects` endpoint -- Required for: Frontend redirect implementation - -:::danger Required for Frontend -Without this permission, you'll get a **403 Forbidden** error when calling the redirects API from your frontend. -::: - ---- - -## 2. Admin Panel Permissions - -For admin users to manage redirects in the Strapi admin panel. - -### Configuration - -1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. -2. Choose the role (e.g., **Editor**, **Author**). -3. Scroll to **Webtools-addon-redirects** plugin section. -4. Enable the permissions needed for this role. -5. Click **Save**. - -### Available Permissions - -#### Access the overview page -- **What it does:** Allows access to the redirects list page -- **Use case:** View all configured redirects -- **Required for:** Seeing the redirects overview in Webtools -- **UI Location:** `/plugins/webtools/redirects` - -#### Create new redirects -- **What it does:** Shows the "Create" button and allows access to the create page -- **Use case:** Let editors add new redirect rules -- **Required for:** Creating redirects via `/plugins/webtools/redirects/new` - -#### Edit existing redirects -- **What it does:** Allows access to the edit page for individual redirects -- **Use case:** Let editors modify existing redirect rules -- **Required for:** Updating redirects via `/plugins/webtools/redirects/:id` - -#### Delete existing redirects -- **What it does:** Shows the delete button and allows deletion of redirects -- **Use case:** Let editors remove outdated redirects -- **Required for:** Removing redirects from the system - -### Permission Combinations - -**For Content Editors:** -- ✅ Access the overview page -- ✅ Create new redirects -- ✅ Edit existing redirects -- ❌ Delete existing redirects (prevent accidental deletions) - -**For Senior Editors:** -- ✅ All permissions - -**For Viewers (read-only):** -- ✅ Access the overview page only - ---- - -## 3. Super Admin Role - -:::info Automatic Access -The **Super Admin** role has all permissions enabled by default and cannot be modified. All configurations are in read-only mode. -::: - -The **Settings** button visible in the permissions UI is for configuring RBAC conditions on other roles, but has no effect on Super Admin permissions. - ---- - -## Testing Permissions - -### Test Public API Access -```bash -curl "http://localhost:1337/api/webtools/redirects" -``` - -### Test Admin Panel Access -1. Create a test user with the configured role -2. Log in as that user -3. Navigate to Webtools → Redirects -4. Verify you can see/create/edit/delete according to permissions - -:::tip -Restart Strapi after making permission changes and clear your browser cache if needed. -::: diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index 5d08ab6d..ca712629 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -168,7 +168,8 @@ const sidebars = { "addons/redirects/getting-started/introduction", "addons/redirects/getting-started/installation", "addons/redirects/getting-started/usage", - "addons/redirects/getting-started/permissions", + "addons/redirects/getting-started/api-permissions", + "addons/redirects/getting-started/admin-permissions", ], }, { From d501986c21cfe03c81d06e115e1cc9bfec78031a Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 15:51:58 +0100 Subject: [PATCH 20/29] Make admin-permissions less 'ai generated' --- .../getting-started/admin-permissions.md | 111 ++++++------------ 1 file changed, 33 insertions(+), 78 deletions(-) diff --git a/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md b/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md index ee800b62..886a91a1 100644 --- a/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md +++ b/packages/docs/docs/addons/redirects/getting-started/admin-permissions.md @@ -6,15 +6,13 @@ slug: /addons/redirects/admin-permissions # 🔐 Admin Panel Permissions -The Redirects addon provides granular permissions for controlling what admin users can do in the Strapi admin panel. +Configure granular permissions to control what administrators can do with redirects in the Strapi admin panel. --- -## Setting up Admin Panel Permissions +## Configuration -For admin users to manage redirects in the Strapi admin panel. - -### Configuration Steps +To configure permissions for a role: 1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. 2. Choose the role (e.g., **Editor**, **Author**). @@ -26,50 +24,33 @@ For admin users to manage redirects in the Strapi admin panel. ## Available Permissions -### Access the overview page -- **What it does:** Allows access to the redirects list page -- **Use case:** View all configured redirects -- **Required for:** Seeing the redirects overview in Webtools -- **UI Location:** `/plugins/webtools/redirects` - -### Create new redirects -- **What it does:** Shows the "Create" button and allows access to the create page -- **Use case:** Let editors add new redirect rules -- **Required for:** Creating redirects via `/plugins/webtools/redirects/new` +The following table lists all available permissions for the Redirects addon in the admin panel: -### Edit existing redirects -- **What it does:** Allows access to the edit page for individual redirects -- **Use case:** Let editors modify existing redirect rules -- **Required for:** Updating redirects via `/plugins/webtools/redirects/:id` - -### Delete existing redirects -- **What it does:** Shows the delete button and allows deletion of redirects -- **Use case:** Let editors remove outdated redirects -- **Required for:** Removing redirects from the system +| Permission | Description | +|------------|-------------| +| **Access the redirects plugin** | Gives access to the redirects overview page at `/plugins/webtools/redirects` | +| **Create** | Allows to create new redirect rules | +| **Read** | Allows to view existing redirect configurations | +| **Update** | Allows to edit existing redirect rules | +| **Delete** | Allows to remove redirect rules from the system | --- ## Permission Combinations -Here are some common permission setups based on different roles: - -### For Content Editors -- ✅ Access the overview page -- ✅ Create new redirects -- ✅ Edit existing redirects -- ❌ Delete existing redirects (prevent accidental deletions) +Common permission setups for different roles: -**Use case:** Content editors who need to manage redirects but shouldn't be able to delete them without approval. +| Role | Access | Create | Read | Update | Delete | +|------|--------|--------|------|--------|--------| +| **Content Editor** | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Senior Editor** | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Viewer** | ✅ | ❌ | ✅ | ❌ | ❌ | -### For Senior Editors -- ✅ All permissions +**Content Editor** - Can manage redirects but cannot delete them to prevent accidental data loss. -**Use case:** Trusted users who can fully manage redirects including deletions. +**Senior Editor** - Has full access to all redirect management features. -### For Viewers (read-only) -- ✅ Access the overview page only - -**Use case:** Stakeholders or reviewers who need to see redirects but not modify them. +**Viewer** - Can view redirects in read-only mode without making changes. --- @@ -83,61 +64,35 @@ The **Settings** button visible in the permissions UI is for configuring RBAC co --- -## Testing Admin Panel Access +## Testing Permissions -### Test Workflow +To verify permissions are configured correctly: 1. Create a test user with the configured role 2. Log in as that user 3. Navigate to **Webtools → Redirects** -4. Verify you can see/create/edit/delete according to permissions - -### Expected Behavior - -**With "Access the overview page" only:** -- Can see the redirects list -- No "Create" button visible -- Cannot access edit or delete actions - -**With all permissions:** -- Can see the redirects list -- "Create" button is visible -- Can click on redirects to edit -- Delete button/action is available +4. Verify the available actions match the configured permissions :::tip -Restart Strapi after making permission changes and clear your browser cache if needed. +Restart Strapi and clear your browser cache after making permission changes. ::: --- ## Troubleshooting -### User cannot access Webtools plugin - -**Problem:** The Webtools menu item is not visible in the sidebar. - -**Solutions:** -- Verify the user has at least "Access the overview page" permission -- Check that the user's role is not disabled +**Webtools menu not visible:** +- Verify the role has at least "Access the redirects plugin" permission enabled - Log out and log back in - Clear browser cache -### Create/Edit/Delete buttons not showing - -**Problem:** User can see redirects but action buttons are missing. - -**Solutions:** -- Verify the specific permissions (create/edit/delete) are enabled for the user's role -- Refresh the page after permission changes -- Check browser console for permission errors - -### Permission changes not taking effect - -**Problem:** After updating permissions, user still has old access level. +**Action buttons missing:** +- Check that Create/Update/Delete permissions are enabled for the role +- Refresh the page +- Check browser console for errors -**Solutions:** -- Ask the user to log out and log back in +**Permission changes not applying:** +- Verify you clicked "Save" after modifying permissions - Restart Strapi server +- Have the user log out and log back in - Clear browser cache and cookies -- Verify you clicked "Save" after changing permissions From dcaaf5d4f61715ff0479eba7dbc064506835d78d Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 15:56:07 +0100 Subject: [PATCH 21/29] Split permissions in admin and api permissions for sitemap + added API token docs --- .../getting-started/admin-permissions.md | 107 ++++++++++++ .../getting-started/api-permissions.md | 156 ++++++++++++++++++ .../sitemap/getting-started/permissions.md | 71 -------- packages/docs/sidebars.ts | 3 +- 4 files changed, 265 insertions(+), 72 deletions(-) create mode 100644 packages/docs/docs/addons/sitemap/getting-started/admin-permissions.md create mode 100644 packages/docs/docs/addons/sitemap/getting-started/api-permissions.md delete mode 100644 packages/docs/docs/addons/sitemap/getting-started/permissions.md diff --git a/packages/docs/docs/addons/sitemap/getting-started/admin-permissions.md b/packages/docs/docs/addons/sitemap/getting-started/admin-permissions.md new file mode 100644 index 00000000..5adede9f --- /dev/null +++ b/packages/docs/docs/addons/sitemap/getting-started/admin-permissions.md @@ -0,0 +1,107 @@ +--- +sidebar_label: 'Admin Permissions' +displayed_sidebar: webtoolsSitemapSidebar +slug: /addons/sitemap/admin-permissions +--- + +# 🔐 Admin Panel Permissions + +Configure permissions to control administrator access to sitemap settings in the Strapi admin panel. + +--- + +## Configuration + +To configure permissions for a role: + +1. Go to **Strapi Admin → Settings → Administration Panel → Roles** +2. Choose the role (e.g., **Editor**, **Author**) +3. Scroll to **Webtools-addon-sitemap** plugin section +4. Enable the permissions needed for this role +5. Click **Save** + +--- + +## Available Permissions + +The following table lists all available permissions for the Sitemap addon in the admin panel: + +| Permission | Description | +|------------|-------------| +| **Access the plugin settings** | Gives access to the sitemap settings page at `/plugins/webtools/sitemap` and allows to view configuration and manually regenerate sitemaps | + +:::info Read-Only Access +The sitemap addon provides primarily read-only access in the admin panel. Configuration changes must be made in `config/plugins.js` and require developer or system administrator access. +::: + +--- + +## What Users Can Do + +Users with "Access the plugin settings" permission can: + +- View sitemap configuration (hostname, exclude drafts, etc.) +- See sitemap generation status and last generation time +- Manually trigger sitemap regeneration +- View generated sitemap URLs +- Access the sitemap index overview + +--- + +## Permission Combinations + +Common permission setups for different roles: + +| Role | Access Settings | +|------|-----------------| +| **Content Editor** | ✅ | +| **Senior Editor** | ✅ | +| **SEO Manager** | ✅ | +| **Viewer** | ❌ | + +**Content Editor / Senior Editor / SEO Manager** - Can view sitemap settings and regenerate sitemaps when content is updated. + +**Viewer** - Cannot access sitemap settings page. + +--- + +## Super Admin Role + +:::info Automatic Access +The **Super Admin** role has all permissions enabled by default and cannot be modified. +::: + +--- + +## Testing Permissions + +To verify permissions are configured correctly: + +1. Create a test user with the configured role +2. Log in as that user +3. Navigate to **Webtools → Sitemap** +4. Verify you can access the settings page + +:::tip +Restart Strapi and clear your browser cache after making permission changes. +::: + +--- + +## Troubleshooting + +**Webtools menu not visible:** +- Verify the role has "Access the plugin settings" permission enabled +- Log out and log back in +- Clear browser cache + +**Cannot regenerate sitemap:** +- Verify the user has "Access the plugin settings" permission +- Check server logs for generation errors +- Ensure content types have published content with URL aliases + +**Permission changes not applying:** +- Verify you clicked "Save" after modifying permissions +- Restart Strapi server +- Have the user log out and log back in +- Clear browser cache and cookies diff --git a/packages/docs/docs/addons/sitemap/getting-started/api-permissions.md b/packages/docs/docs/addons/sitemap/getting-started/api-permissions.md new file mode 100644 index 00000000..bc6bc4d3 --- /dev/null +++ b/packages/docs/docs/addons/sitemap/getting-started/api-permissions.md @@ -0,0 +1,156 @@ +--- +sidebar_label: 'API Permissions' +displayed_sidebar: webtoolsSitemapSidebar +slug: /addons/sitemap/api-permissions +--- + +# 🔐 API Permissions + +The Sitemap addon exposes sitemap XML files publicly by default. No permission configuration is required for standard usage. + +--- + +## Public Sitemap Access + +The sitemap XML files are automatically accessible to the public: + +- `/sitemap.xml` - Main sitemap or sitemap index +- `/sitemap/[name].xml` - Individual sitemaps (when using sitemap index) + +:::info Automatic Configuration +These endpoints are automatically enabled during bootstrap for the **Public** role. No manual permission configuration is needed. +::: + +--- + +## Testing Sitemap Access + +### Test Main Sitemap + +```bash +curl "http://localhost:1337/sitemap.xml" +``` + +**Expected response:** +```xml + + + + https://example.com/page + 2025-01-15 + + + +``` + +### Test Sitemap Index + +If you have multiple sitemaps configured: + +```bash +curl "http://localhost:1337/sitemap.xml" +``` + +**Expected response:** +```xml + + + + https://example.com/sitemap/articles.xml + 2025-01-15 + + + +``` + +--- + +## Advanced: Restricting Sitemap Access + +If you need to restrict sitemap access (e.g., for staging environments), you can use middleware or routes customization. + +### Option 1: Using Middleware + +Create a custom middleware in `src/middlewares/sitemap-auth.js`: + +```javascript +module.exports = (config, { strapi }) => { + return async (ctx, next) => { + if (ctx.request.url.startsWith('/sitemap')) { + // Add your custom authorization logic + const token = ctx.request.headers['x-sitemap-token']; + + if (token !== process.env.SITEMAP_ACCESS_TOKEN) { + return ctx.unauthorized('Invalid sitemap access token'); + } + } + + await next(); + }; +}; +``` + +Register in `config/middlewares.js`: + +```javascript +module.exports = [ + // ... other middlewares + 'global::sitemap-auth', +]; +``` + +### Option 2: Using API Tokens + +For programmatic access (e.g., SEO tools, monitoring services), you can create read-only API tokens. + +1. Go to **Strapi Admin → Settings → API Tokens** +2. Click **Create new API Token** +3. Configure the token: + - **Name**: "SEO Tool Access" + - **Token type**: Read-only + - **Token duration**: Unlimited or as needed + +4. Use the token with `Authorization` header: + +```bash +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/sitemap.xml" +``` + +:::tip For Build-Time Access +If you're fetching sitemaps during static site generation (Next.js, Gatsby), use API tokens stored in environment variables to access Strapi during builds. +::: + +--- + +## robots.txt Configuration + +The sitemap location should be declared in your `robots.txt` file. See the [robots.txt guide](/addons/sitemap/robots-txt) for configuration details. + +--- + +## Troubleshooting + +**404 Not Found:** +- Verify the sitemap addon is installed and enabled +- Check that at least one content type with webtools is published +- Ensure sitemap has been generated (manually or via cron) + +**Empty sitemap:** +- Verify content is published (not draft) +- Check "Exclude drafts" setting is properly configured +- Ensure URL aliases are generated for content + +**CORS issues:** +- Configure CORS in `config/middlewares.js` if accessing from browsers: +```javascript +module.exports = [ + // ... + { + name: 'strapi::cors', + config: { + origin: ['http://localhost:3000', 'https://your-frontend.com'], + }, + }, +]; +``` diff --git a/packages/docs/docs/addons/sitemap/getting-started/permissions.md b/packages/docs/docs/addons/sitemap/getting-started/permissions.md deleted file mode 100644 index 4c5c8f7c..00000000 --- a/packages/docs/docs/addons/sitemap/getting-started/permissions.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -sidebar_label: 'Permissions' -displayed_sidebar: webtoolsSitemapSidebar -slug: /addons/sitemap/permissions ---- - -# 🔐 Permissions - -The Sitemap addon has minimal permission requirements since it's primarily a read-only feature. - ---- - -## Admin Panel Permission - -### Configuration - -1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. -2. Choose the role (e.g., **Editor**, **Author**). -3. Under **Webtools-addon-sitemap** plugin section. -4. Enable **Access the plugin settings**. -5. Click **Save**. - -### Access the plugin settings - -- **What it does:** Allows access to the sitemap settings page -- **Use case:** View sitemap configuration and regenerate sitemaps -- **Required for:** Accessing `/plugins/webtools/sitemap` -- **Capabilities:** - - View sitemap settings (hostname, exclude drafts, etc.) - - See sitemap generation status - - Manually regenerate sitemaps - - View sitemap URLs - -:::info Read-Only Access -The sitemap addon provides primarily read-only access. Configuration changes are made in `config/plugins.js` and require developer/system admin access. -::: - ---- - -## Public Access - -The sitemap XML files are publicly accessible by default: - -- `/sitemap.xml` - Main sitemap or sitemap index -- `/sitemap/[name].xml` - Individual sitemaps - -**No permission configuration needed** - these endpoints are automatically enabled during bootstrap for the Public role. - ---- - -## Super Admin Role - -:::info Automatic Access -The **Super Admin** role has all permissions enabled by default and cannot be modified. -::: - ---- - -## Testing Permissions - -### Test Admin Panel Access -1. Log in with a user that has the "Access the plugin settings" permission -2. Navigate to Webtools → Sitemap -3. Verify you can view settings and regenerate sitemaps - -### Test Public Sitemap Access -```bash -curl "http://localhost:1337/sitemap.xml" -``` - -The sitemap should be accessible without authentication. diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index ca712629..29b7dcf7 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -117,7 +117,8 @@ const sidebars = { "addons/sitemap/getting-started/sitemap-index", "addons/sitemap/getting-started/robots-txt", "addons/sitemap/getting-started/cli", - "addons/sitemap/getting-started/permissions", + "addons/sitemap/getting-started/api-permissions", + "addons/sitemap/getting-started/admin-permissions", ], }, { From 91cc26d21152fbe02315f11c65dc0d41e4d3b029 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 16:04:03 +0100 Subject: [PATCH 22/29] Split permissions in admin and api permissions for webtools core docs --- .../docs/getting-started/admin-permissions.md | 117 +++++++++ .../docs/getting-started/api-permissions.md | 248 ++++++++++++++++++ .../docs/docs/getting-started/permissions.md | 138 ---------- packages/docs/sidebars.ts | 3 +- 4 files changed, 367 insertions(+), 139 deletions(-) create mode 100644 packages/docs/docs/getting-started/admin-permissions.md create mode 100644 packages/docs/docs/getting-started/api-permissions.md delete mode 100644 packages/docs/docs/getting-started/permissions.md diff --git a/packages/docs/docs/getting-started/admin-permissions.md b/packages/docs/docs/getting-started/admin-permissions.md new file mode 100644 index 00000000..cfdc9e2d --- /dev/null +++ b/packages/docs/docs/getting-started/admin-permissions.md @@ -0,0 +1,117 @@ +--- +sidebar_label: 'Admin Permissions' +displayed_sidebar: webtoolsSidebar +slug: /admin-permissions +--- + +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + +# 🔐 Admin Panel Permissions + +Configure granular permissions to control what administrators can do with Webtools in the Strapi admin panel. + +--- + +## Configuration + +To configure permissions for a role: + +1. Go to **Strapi Admin → Settings → Administration Panel → Roles** +2. Choose the role (e.g., **Author**, **Editor**) +3. Under **Plugins** → **Webtools** enable the permissions you need +4. Click **Save** + + + +--- + +## Available Permissions + +The following table lists all available permissions for Webtools in the admin panel: + +| Permission | Description | +|------------|-------------| +| **Access the overview page** | Gives access to the main Webtools overview page at `/plugins/webtools` | +| **Access the URL alias list** | Allows to view and manage all URL aliases created for content | +| **Access the URL alias patterns** | Allows to configure URL pattern templates (list, create, edit) | +| **Access the URL alias sidebar** | Shows the Webtools panel in the Content Manager sidebar when editing content | + +--- + +## Permission Combinations + +Common permission setups for different roles: + +| Role | Overview | URL Alias List | URL Patterns | Sidebar | +|------|----------|----------------|--------------|---------| +| **Content Editor** | ❌ | ✅ | ❌ | ✅ | +| **Senior Editor** | ✅ | ✅ | ❌ | ✅ | +| **Admin** | ✅ | ✅ | ✅ | ✅ | +| **Viewer** | ❌ | ✅ | ❌ | ❌ | + +**Content Editor** - Can view URLs when editing content and see the URL alias list, but cannot modify patterns or access the overview page. + +**Senior Editor** - Can access the overview page and manage URL aliases, but cannot modify URL patterns to prevent accidental changes to URL generation rules. + +**Admin** - Has full access to all Webtools features including URL pattern management. + +**Viewer** - Can only view the URL alias list in read-only mode. + +--- + +## Super Admin Role + +:::info Automatic Access +The **Super Admin** role has all permissions enabled by default and cannot be modified. +::: + +:::tip RBAC Conditions +For non-Super-Admin roles, you can click the **Settings** button next to permissions to add conditional access rules (e.g., "can edit when user is creator"). See [Strapi RBAC documentation](https://docs.strapi.io/dev-docs/configurations/rbac) for details. +::: + +--- + +## Testing Permissions + +To verify permissions are configured correctly: + +1. Create a test user with the configured role +2. Log in as that user +3. Navigate to **Webtools** in the admin panel +4. Verify the available pages and actions match the configured permissions + +:::tip +Restart Strapi and clear your browser cache after making permission changes. +::: + +--- + +## Troubleshooting + +**Webtools menu not visible:** +- Verify the role has at least one Webtools permission enabled +- Log out and log back in +- Clear browser cache + +**URL alias sidebar not showing in Content Manager:** +- Check that "Access the URL alias sidebar" permission is enabled +- Verify the content-type has Webtools enabled in its schema +- Refresh the page + +**Cannot access URL patterns page:** +- Verify "Access the URL alias patterns" permission is enabled for the role +- Check that the user's role is not disabled +- Clear browser cache + +**Permission changes not applying:** +- Verify you clicked "Save" after modifying permissions +- Restart Strapi server +- Have the user log out and log back in +- Clear browser cache and cookies diff --git a/packages/docs/docs/getting-started/api-permissions.md b/packages/docs/docs/getting-started/api-permissions.md new file mode 100644 index 00000000..259ca92b --- /dev/null +++ b/packages/docs/docs/getting-started/api-permissions.md @@ -0,0 +1,248 @@ +--- +sidebar_label: 'API Permissions' +displayed_sidebar: webtoolsSidebar +slug: /api-permissions +--- + +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + +# 🔐 API Permissions + +Webtools exposes API endpoints that your frontend application uses to fetch content by URL path. This requires proper permissions configuration. + +:::danger Required for Frontend +Without the proper permissions, you'll get a **403 Forbidden** error when calling: +- `GET /api/webtools/router?path=...` +- `GET /api/webtools/url-alias` +::: + +--- + +## 1. Content-Type Permissions + +For each content-type where you've enabled Webtools, you need to enable the **find** permission. + +### Configuration Steps + +1. Go to **Strapi Admin → Settings → Users & Permissions plugin → Roles** +2. Select the role (e.g., **Public** or **Authenticated**) +3. Under **Application** you'll find your enabled content-types (e.g., `page`, `article`) +4. Check **Find** (and **Find One** if desired) +5. Click **Save** + + + +### What it enables + +- Allows the router endpoint to return content data for your content-types +- Required for fetching content by URL path via `/api/webtools/router` + +--- + +## 2. Webtools Plugin Permissions + +Enable the Webtools API endpoints for your frontend application. + +### Configuration Steps + +1. In the same role (e.g., **Public**) scroll to the **Webtools** section +2. Check: + - **Router: find** + - **URL Alias: find** +3. Click **Save** + + + +### What it enables + +| Permission | Endpoint | Description | +|------------|----------|-------------| +| **Router: find** | `GET /api/webtools/router?path=...` | Allows to fetch content by URL path for routing in frontend applications | +| **URL Alias: find** | `GET /api/webtools/url-alias` | Allows to fetch all URL aliases for generating static routes or sitemaps | + +--- + +## Access via API Tokens + +In addition to the Users & Permissions plugin (for public and authenticated users), you can use **API Tokens** for programmatic access to Webtools endpoints. + +### When to use API Tokens + +- **Build-time data fetching**: Static site generators (Next.js, Gatsby, etc.) +- **Server-to-server communication**: Backend services fetching content by URL +- **CI/CD pipelines**: Automated testing or validation +- **Development tools**: Local development scripts fetching routes + +### Creating an API Token + +1. Go to **Strapi Admin → Settings → API Tokens** +2. Click **Create new API Token** +3. Configure the token: + - **Name**: e.g., "Frontend Build Token" or "Webtools API Access" + - **Description**: Optional description of the token's purpose + - **Token duration**: Unlimited, 7 days, 30 days, or 90 days + - **Token type**: Choose based on your needs: + - **Read-only**: Can only fetch data (recommended for webtools) + - **Full access**: Can create, update, and delete (use with caution) + - **Custom**: Fine-grained permissions (see below) + +4. Click **Save** and copy the generated token immediately (it won't be shown again) + +### Configuring Custom Permissions for API Tokens + +For better security, use **Custom** token type with specific permissions: + +1. Select **Custom** as Token type +2. Enable permissions for your content-types: + - Under each content-type: **find** and **findOne** +3. Scroll to **Webtools** section +4. Enable: + - **Router: find** + - **URL Alias: find** + +:::tip Security Best Practice +Use **Read-only** tokens or **Custom** tokens with only find permissions enabled for frontend applications. Never expose tokens with write permissions in client-side code. +::: + +### Using the API Token + +Include the token in the `Authorization` header when making requests: + +```bash +# Fetch content by URL path +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/api/webtools/router?path=/about-us" + +# Fetch all URL aliases +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/api/webtools/url-alias" +``` + +**Next.js example (server-side):** +```javascript +// app/[...slug]/page.tsx +export async function generateStaticParams() { + const response = await fetch('https://your-strapi.com/api/webtools/url-alias', { + headers: { + 'Authorization': `Bearer ${process.env.STRAPI_API_TOKEN}`, + }, + }); + const aliases = await response.json(); + + return aliases.data.map((alias) => ({ + slug: alias.attributes.url_path.split('/').filter(Boolean), + })); +} + +export default async function Page({ params }) { + const path = '/' + params.slug.join('/'); + + const response = await fetch( + `https://your-strapi.com/api/webtools/router?path=${path}`, + { + headers: { + 'Authorization': `Bearer ${process.env.STRAPI_API_TOKEN}`, + }, + } + ); + + const data = await response.json(); + // Render your page... +} +``` + +**Important:** Store API tokens in environment variables (`.env.local`), never commit them to version control. + +--- + +## Testing API Access + +### Test with Public/Authenticated role + +```bash +# Without authentication (requires Public role permissions) +curl "http://localhost:1337/api/webtools/router?path=/about-us" + +# With user JWT token (requires Authenticated role permissions) +curl -H "Authorization: Bearer USER_JWT_TOKEN" \ + "http://localhost:1337/api/webtools/router?path=/about-us" +``` + +### Test with API Token + +```bash +curl -H "Authorization: Bearer YOUR_API_TOKEN" \ + "http://localhost:1337/api/webtools/router?path=/about-us" +``` + +**Expected response:** +```json +{ + "data": { + "id": 1, + "documentId": "abc123", + "title": "About Us", + "content": "...", + // ... other content fields + }, + "meta": { + "contentType": "api::page.page" + } +} +``` + +:::tip +Restart Strapi after making permission changes and clear your browser cache if needed. +::: + +--- + +## Troubleshooting + +**403 Forbidden Error:** +- Verify the correct role (Public/Authenticated) has permissions enabled for: + - Content-type **find** permission + - Webtools **Router: find** permission + - Webtools **URL Alias: find** permission (if using that endpoint) +- If using API token, verify it's valid and has correct permissions +- Restart Strapi after permission changes +- Check that the token hasn't expired + +**API Token not working:** +- Ensure token is included in `Authorization: Bearer TOKEN` header +- Verify token hasn't expired +- Check token type has necessary permissions (not Read-only for write operations) +- Regenerate token if needed + +**Content returns empty:** +- Verify content is published (not draft) +- Check that URL alias exists for the content +- Ensure content-type has Webtools enabled in schema +- Verify content has a valid `url_alias` relation + +**CORS issues in frontend:** +- Configure CORS in `config/middlewares.js`: +```javascript +module.exports = [ + // ... + { + name: 'strapi::cors', + config: { + origin: ['http://localhost:3000', 'https://your-frontend.com'], + }, + }, +]; +``` diff --git a/packages/docs/docs/getting-started/permissions.md b/packages/docs/docs/getting-started/permissions.md deleted file mode 100644 index 5ff69791..00000000 --- a/packages/docs/docs/getting-started/permissions.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -sidebar_label: 'Permissions' -displayed_sidebar: webtoolsSidebar -slug: /permissions ---- - -import ThemedImage from '@theme/ThemedImage'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -# 🔐 Role-Based Access Control (RBAC) - -After installation, review Webtools permissions per role in Settings so your front-end can access the required endpoints. - -Without the proper permissions, you'll get a **403 Forbidden** error when calling: -- `GET /api/webtools/router?path=…` -- `GET /api/webtools/url-alias` - -Below are the three permission categories you need to configure. - ---- - -## 1. Content-Type "find" permissions - -For each content-type where you've enabled Webtools, you need to open up the standard **find** permission. - -1. Go to **Strapi Admin → Settings → Users & Permissions plugin → Roles**. -2. Select the role (e.g., **Public**). -3. Under **Application** you'll find your enabled content-types (e.g., `page`, `article`). -4. Check **Find** (and **Find One** if desired). -5. Click **Save**. - - - ---- - -## 2. Webtools plugin permissions - -Enable the Webtools endpoints for your front-end: - -1. In the same role (e.g., **Public**) scroll to the **Webtools** section. -2. Check: - - **Router: find** - - **URL Alias: find** -3. Click **Save**. - - - ---- - -## 3. Admin Panel roles - -Want your editors/admins to manage Webtools settings? Configure admin panel permissions: - -### How to Configure - -1. Go to **Strapi Admin → Settings → Administration Panel → Roles**. -2. Choose the role (e.g., **Author**, **Editor**). -3. Under **Plugins** → **Webtools** enable the permissions you need. -4. Click **Save**. - - - -### Available Permissions - -#### Access the overview page -- **What it does:** Allows access to the main Webtools overview page at `/plugins/webtools` -- **Use case:** Give users a dashboard view of all Webtools features -- **Required for:** Viewing the Webtools main navigation and overview - -#### Access the URL alias list -- **What it does:** Allows access to the URL Aliases list page -- **Use case:** Let editors view and manage all URL aliases created for content -- **Required for:** Viewing the list of all generated URLs - -#### Access the URL alias patterns -- **What it does:** Allows access to the URL Patterns management pages (list, create, edit) -- **Use case:** Give admins ability to configure URL pattern templates -- **Required for:** Managing URL generation rules (e.g., `/blog/[title]`) - -#### Access the URL alias sidebar -- **What it does:** Shows/hides the Webtools panel in the Content Manager sidebar -- **Use case:** Let content editors see and manage URLs when editing content -- **Required for:** Viewing URL information in the Content Manager - -### Permission Combinations - -**For Content Editors:** -- ✅ Access the URL alias sidebar (to see URLs when editing) -- ✅ Access the URL alias list (to view all URLs) -- ❌ Access the URL alias patterns (prevent pattern changes) -- ❌ Access the overview page (optional) - -**For Admins:** -- ✅ All permissions (full access) - -### Notes - -:::info Super Admin -The **Super Admin** role has all permissions enabled by default and cannot be modified. The Settings button visible in the permissions UI allows adding RBAC conditions for other roles, but is read-only for Super Admin. -::: - -:::tip RBAC Conditions -For non-Super-Admin roles, you can click the **Settings** button next to permissions to add conditional access rules (e.g., "can edit when user is creator"). See [Strapi RBAC documentation](https://docs.strapi.io/dev-docs/configurations/rbac) for details. -::: - ---- - -## Test your permissions - -After saving: - -```bash -curl "http://localhost:1337/api/webtools/router?path=/about-page" -``` - -You should now receive data instead of a 403 error. - -:::tip -Restart Strapi after making changes and clear the cache if necessary. -::: diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index 29b7dcf7..7e1411d7 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -26,7 +26,8 @@ const sidebars = { "getting-started/usage", "getting-started/url-pattern", "getting-started/url-alias", - "getting-started/permissions", + "getting-started/api-permissions", + "getting-started/admin-permissions", "getting-started/troubleshooting", ], }, From 3478fda1fd603efefc2648816cc79117c2ae73db Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:56:17 +0100 Subject: [PATCH 23/29] activation_id clarification --- .../docs/getting-started/troubleshooting.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/docs/docs/getting-started/troubleshooting.md b/packages/docs/docs/getting-started/troubleshooting.md index c1a5dc4b..b6fb26eb 100644 --- a/packages/docs/docs/getting-started/troubleshooting.md +++ b/packages/docs/docs/getting-started/troubleshooting.md @@ -33,7 +33,7 @@ Multiple warnings about unmet peer dependencies during installation. error: [webtools]: License key activation is not valid. Remove the activation_id from your package.json to issue a new activation for this project. ``` -This error occurs when the stored license activation is no longer valid. This can happen when: +This error occurs when the stored license activation is no longer valid. The `activation_id` is stored in your `package.json` under `strapi.webtools.activation_id`. This can happen when: - You moved the project to a different machine - You reinstalled dependencies or changed the project structure @@ -43,7 +43,7 @@ This error occurs when the stored license activation is no longer valid. This ca **Solution:** Remove the activation ID and restart Strapi to trigger a new activation: 1. Open your `package.json` file -2. Look for a field named `activation_id` (usually near the top level) +2. Find the `strapi.webtools.activation_id` field (located inside the `strapi` object) 3. Remove the entire `activation_id` field and its value 4. Save the file 5. Restart your Strapi server @@ -56,9 +56,13 @@ Before: ```json { "name": "my-strapi-project", - "activation_id": "abc123...", "version": "1.0.0", - ... + "strapi": { + "uuid": "...", + "webtools": { + "activation_id": "..." + } + } } ``` @@ -67,7 +71,10 @@ After: { "name": "my-strapi-project", "version": "1.0.0", - ... + "strapi": { + "uuid": "...", + "webtools": {} + } } ``` From 943cd9500fdaa2d4c8b945ebfb701ce986989c8f Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:00:30 +0100 Subject: [PATCH 24/29] Update 'URL is incorrect' (slugify) text --- packages/docs/docs/getting-started/troubleshooting.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/docs/docs/getting-started/troubleshooting.md b/packages/docs/docs/getting-started/troubleshooting.md index b6fb26eb..1afab33f 100644 --- a/packages/docs/docs/getting-started/troubleshooting.md +++ b/packages/docs/docs/getting-started/troubleshooting.md @@ -93,7 +93,15 @@ npx webtools-cli setup-license ## Pattern & URL Issues ### URL is incorrect -The Webtools plugin applies it's own slugify function to your URLs. That means that if you have already have a slugified field, which you then use in an URL pattern, it will be slugified again, potentially causing incorrect URLs. If you want you can disable the slugify function of Webtools by updating the slugify configuration. + +Webtools applies its own slugify function to URL patterns. If you're using an already-slugified field in your pattern, it will be slugified twice, resulting in incorrect URLs. + +**Example problem:** +- Field value: `my-blog-post` (already slugified) +- Pattern: `/blog/[title]` +- Result: `/blog/my--blog--post` (double slugified) + +**Solution:** Disable the slugify function in your Webtools configuration if you're using pre-slugified fields. See [slugify configuration docs](/configuration/slugify) From cb991ca8affdfcc335b551953b42783ddfcb895a Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:13:03 +0100 Subject: [PATCH 25/29] Configuration Issues - Clarification about default language URL type --- .../docs/getting-started/troubleshooting.md | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/docs/docs/getting-started/troubleshooting.md b/packages/docs/docs/getting-started/troubleshooting.md index 1afab33f..64b8019f 100644 --- a/packages/docs/docs/getting-started/troubleshooting.md +++ b/packages/docs/docs/getting-started/troubleshooting.md @@ -188,22 +188,37 @@ Origin null is not allowed by Access-Control-Allow-Origin ## Configuration Issues -### Default Language URL Type -Controls how the default locale appears in URLs: +### Confused about "Default Language URL Type"? -- **Disabled**: All URLs use same format `/path` -- **Default language URL of bundles**: Default locale gets `/en/path`, others `/nl/path` -- **Other**: Custom locale handling +This sitemap setting controls whether your default language appears in URLs. -Choose based on your multilingual URL structure needs. +**Problem:** Not sure which option to choose in the sitemap settings. -### URL Bundle Configuration -Each content type can have multiple bundles with different: -- Change frequency (hourly, daily, monthly) -- Priority settings (0.1 - 1.0) -- Locale-specific configurations +**Options explained:** -This allows fine-grained control over how different content appears in your sitemap. +| Option | Default Language URL | Other Language URL | Use When | +|--------|---------------------|-------------------|----------| +| **Disabled** | `/about` | `/about` | Single language site, or all locales use same URL format | +| **Default language URL of bundles** | `/en/about` | `/nl/about` | You want all languages (including default) to have locale prefixes | +| **Other** | `/about` | `/nl/about` | Only non-default languages should have locale prefixes | + +**Example:** +If your default language is English and you choose "Other": +- English page: `https://example.com/about` +- Dutch page: `https://example.com/nl/about` + +### Multiple sitemap bundles for same content type? + +You can add the same content type multiple times to sitemap bundles. + +**Why would you do this?** + +Each bundle can have different settings for different locales or priorities: + +- **Bundle 1**: English articles with `changefreq: daily` and `priority: 0.8` +- **Bundle 2**: Dutch articles with `changefreq: weekly` and `priority: 0.6` + +This allows fine-grained control over how different content and locales appear in your sitemap. ## Still Having Issues? From e5336e1ecdf65694633c4a1f874aac75f3ae91a1 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:22:55 +0100 Subject: [PATCH 26/29] Changed text from 30 day trial to 7 day trial --- packages/docs/docs/cli/setup-license.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/docs/cli/setup-license.md b/packages/docs/docs/cli/setup-license.md index 2e0053cb..c42212d0 100644 --- a/packages/docs/docs/cli/setup-license.md +++ b/packages/docs/docs/cli/setup-license.md @@ -30,9 +30,9 @@ Select this option if you already have a purchased license key. You'll be prompt ### 2. Get me a trial -Select this option to start a **30-day free trial** of the Essential plan. The trial includes: +Select this option to start a **7-day free trial** of the Essential plan. The trial includes: - [Redirects addon](/webtools/addons/redirects) -- [Internal Links addon](/webtools/addons/links) +- [Links addon](/webtools/addons/links) #### Trial Process From 54b4cf7728da9aa89eefafc2d89cc31167a6a4bf Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:32:20 +0100 Subject: [PATCH 27/29] remove sitemap-specific content from core docs --- .../docs/docs/configuration/introduction.md | 10 --- .../docs/getting-started/api-permissions.md | 2 +- .../docs/getting-started/troubleshooting.md | 61 ------------------- packages/docs/docs/getting-started/usage.md | 2 +- 4 files changed, 2 insertions(+), 73 deletions(-) diff --git a/packages/docs/docs/configuration/introduction.md b/packages/docs/docs/configuration/introduction.md index 2ae9d43e..573e0f09 100644 --- a/packages/docs/docs/configuration/introduction.md +++ b/packages/docs/docs/configuration/introduction.md @@ -36,16 +36,6 @@ export default ({ env }) => ({ | `slugify` | function | `kebabCase(deburr(toLower()))` | Transform field values into URL-safe slugs (converts "My Title" to "my-title") | | `unique_per_locale` | boolean | `false` | Allow same URL alias across different locales | -## URL bundle settings (sitemap) - -When configuring sitemap URL bundles, each bundle supports: - -| Setting | Options | Description | -|---------|---------|-------------| -| **Change frequency** | `hourly`, `daily`, `weekly`, `monthly`, `yearly` | How often search engines should crawl these URLs | -| **Priority** | `0.1` - `1.0` | Relative importance of URLs in this bundle | -| **Default language URL type** | `Disabled`, `Default language URL of bundles`, `Other` | How default locale appears in URLs | - :::tip Pattern tokens Available tokens for URL patterns: `[documentId]`, `[locale]`, `[pluralName]`, and any field from your content type. Type `[` in the pattern field to see all available options. ::: diff --git a/packages/docs/docs/getting-started/api-permissions.md b/packages/docs/docs/getting-started/api-permissions.md index 259ca92b..01f3ea0b 100644 --- a/packages/docs/docs/getting-started/api-permissions.md +++ b/packages/docs/docs/getting-started/api-permissions.md @@ -71,7 +71,7 @@ Enable the Webtools API endpoints for your frontend application. | Permission | Endpoint | Description | |------------|----------|-------------| | **Router: find** | `GET /api/webtools/router?path=...` | Allows to fetch content by URL path for routing in frontend applications | -| **URL Alias: find** | `GET /api/webtools/url-alias` | Allows to fetch all URL aliases for generating static routes or sitemaps | +| **URL Alias: find** | `GET /api/webtools/url-alias` | Allows to fetch all URL aliases for generating static routes | --- diff --git a/packages/docs/docs/getting-started/troubleshooting.md b/packages/docs/docs/getting-started/troubleshooting.md index 64b8019f..2c63bbd8 100644 --- a/packages/docs/docs/getting-started/troubleshooting.md +++ b/packages/docs/docs/getting-started/troubleshooting.md @@ -118,33 +118,6 @@ Some content types require locale selection when creating patterns. **Explanation:** Multi-language content types need locale-specific patterns. This is normal behavior for internationalized content. -### Multiple content type bundles -Content types can be selected multiple times in sitemap bundles. - -**Use case:** Each bundle can have different settings (change frequency, priority, locale-specific configurations). - -## Sitemap Issues - -### Invalid URL error (500) -``` -TypeError [ERR_INVALID_URL]: Invalid URL -``` - -**Solution:** Ensure hostname includes protocol prefix: -- ✅ Correct: `http://localhost:1337` -- ❌ Wrong: `localhost:1337` - -### Generate sitemap button stuck -UI becomes unresponsive after sitemap generation error (usually caused by incorrect hostname format). - -**Solution:** Hard refresh browser (Ctrl+R) to reset the interface state. - -### Router permissions error -500 error when generating sitemap, even with correct URL format. - -**Solution:** Enable router permissions in **Settings > Users & Permissions > Public**: -- `webtools.router.find` - ## API Issues ### Returns all URLs instead of one @@ -186,40 +159,6 @@ Origin null is not allowed by Access-Control-Allow-Origin } ``` -## Configuration Issues - -### Confused about "Default Language URL Type"? - -This sitemap setting controls whether your default language appears in URLs. - -**Problem:** Not sure which option to choose in the sitemap settings. - -**Options explained:** - -| Option | Default Language URL | Other Language URL | Use When | -|--------|---------------------|-------------------|----------| -| **Disabled** | `/about` | `/about` | Single language site, or all locales use same URL format | -| **Default language URL of bundles** | `/en/about` | `/nl/about` | You want all languages (including default) to have locale prefixes | -| **Other** | `/about` | `/nl/about` | Only non-default languages should have locale prefixes | - -**Example:** -If your default language is English and you choose "Other": -- English page: `https://example.com/about` -- Dutch page: `https://example.com/nl/about` - -### Multiple sitemap bundles for same content type? - -You can add the same content type multiple times to sitemap bundles. - -**Why would you do this?** - -Each bundle can have different settings for different locales or priorities: - -- **Bundle 1**: English articles with `changefreq: daily` and `priority: 0.8` -- **Bundle 2**: Dutch articles with `changefreq: weekly` and `priority: 0.6` - -This allows fine-grained control over how different content and locales appear in your sitemap. - ## Still Having Issues? 1. **Check server logs** for detailed error messages diff --git a/packages/docs/docs/getting-started/usage.md b/packages/docs/docs/getting-started/usage.md index aef3ab38..77c832f6 100644 --- a/packages/docs/docs/getting-started/usage.md +++ b/packages/docs/docs/getting-started/usage.md @@ -65,7 +65,7 @@ After enabling Webtools for your content types: 1. **Create URL patterns** - See [URL pattern](/url-pattern) documentation 2. **Bulk generate URLs** - Go to Webtools > All URLs to create aliases for existing content -3. **Generate sitemap** - Configure and generate XML sitemap with your URLs +3. **[Optional] Install addons** - Add extra features like [Sitemap](/addons/sitemap), [Redirects](/addons/redirects), or [Links](/addons/links) :::tip Pattern discovery Type `[` in the pattern field to see available fields from your content type. From 4b0a016f2c6bdc9a52008e823b5559e50b6c13d2 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:55:12 +0100 Subject: [PATCH 28/29] add sitemap-specific docs inside addon docs --- .../getting-started/troubleshooting.md | 149 ++++++++++++++++++ .../addons/sitemap/getting-started/usage.md | 25 ++- packages/docs/sidebars.ts | 1 + 3 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 packages/docs/docs/addons/sitemap/getting-started/troubleshooting.md diff --git a/packages/docs/docs/addons/sitemap/getting-started/troubleshooting.md b/packages/docs/docs/addons/sitemap/getting-started/troubleshooting.md new file mode 100644 index 00000000..bfe1167b --- /dev/null +++ b/packages/docs/docs/addons/sitemap/getting-started/troubleshooting.md @@ -0,0 +1,149 @@ +--- +sidebar_label: 'Troubleshooting' +displayed_sidebar: webtoolsSitemapSidebar +slug: /addons/sitemap/troubleshooting +--- + +# 🔧 Troubleshooting + +Common issues and solutions when working with the Sitemap addon. + +--- + +## Generation Issues + +### Invalid URL error (500) +``` +TypeError [ERR_INVALID_URL]: Invalid URL +``` + +**Cause:** The hostname setting is missing the protocol prefix. + +**Solution:** Ensure hostname includes protocol prefix in your sitemap settings: +- ✅ Correct: `http://localhost:1337` or `https://example.com` +- ❌ Wrong: `localhost:1337` or `example.com` + +Go to **Webtools → Sitemap → Settings** and update the hostname field. + +--- + +### Generate sitemap button stuck + +**Problem:** UI becomes unresponsive after clicking "Generate sitemap" button. + +**Cause:** Usually occurs after a sitemap generation error (such as incorrect hostname format). + +**Solution:** Hard refresh your browser to reset the interface state: +- **Windows/Linux:** `Ctrl + Shift + R` or `Ctrl + F5` +- **Mac:** `Cmd + Shift + R` + +After refreshing, fix the underlying issue (e.g., hostname format) before generating again. + +--- + +### Router permissions error + +**Problem:** 500 error when generating sitemap, even with correct hostname format. + +**Cause:** The sitemap generator needs access to the Webtools router endpoint to fetch content. + +**Solution:** Enable router permissions for the Public role: + +1. Go to **Settings → Users & Permissions plugin → Roles** +2. Select **Public** role +3. Scroll to **Webtools** section +4. Check **Router: find** +5. Click **Save** + +See the [API Permissions documentation](/webtools/addons/sitemap/api-permissions) for more details. + +--- + +### Empty sitemap generated + +**Problem:** Sitemap generates successfully but contains no URLs. + +**Possible causes:** +- Content is in draft status (not published) +- URL aliases not generated for content +- Content type doesn't have Webtools enabled +- "Exclude drafts" setting is enabled but content is considered draft + +**Solution:** +1. Verify content is **published** (not draft) +2. Go to **Webtools → All URLs** and check if URL aliases exist +3. If no aliases exist, use the bulk generate feature +4. Verify content type has Webtools enabled in schema +5. Check **Webtools → Sitemap → Settings** and review "Exclude drafts" setting + +--- + +## Configuration Issues + +### Sitemap not accessible + +**Problem:** Getting 404 when accessing `/sitemap.xml` or `/sitemap/index.xml`. + +**Solution:** +- Verify the sitemap addon is installed and enabled +- Ensure at least one URL bundle or custom URL is configured +- Generate the sitemap manually via admin panel +- Restart Strapi server + +--- + +### Confused about "Default Language URL Type"? + +**Problem:** Not sure which option to choose in the bundle settings. + +This setting controls how URLs for different locales appear in your sitemap for multilingual content. + +**Options explained:** + +| Option | Default Language URL | Other Language URL | Use When | +|--------|---------------------|-------------------|----------| +| **Disabled** | `/about` | `/about` | Single language site, or all locales use same URL format | +| **Default language URL of bundles** | `/en/about` | `/nl/about` | You want all languages (including default) to have locale prefixes | +| **Other** | `/about` | `/nl/about` | Only non-default languages should have locale prefixes | + +**Example:** +If your default language is English and you choose "Other": +- English page: `https://example.com/about` +- Dutch page: `https://example.com/nl/about` + +--- + +## Performance Issues + +### Sitemap generation takes too long + +**Problem:** Sitemap generation times out or takes several minutes. + +**Possible causes:** +- Too many URLs in a single sitemap (exceeds 50,000 limit) +- Large number of content entries +- Complex URL pattern processing + +**Solution:** +1. Use [sitemap indexes](/webtools/addons/sitemap/sitemap-index) to split large sitemaps +2. Adjust the `limit` setting in configuration to reduce URLs per sitemap +3. Enable [cron-based generation](/webtools/addons/sitemap/configuration/cron) instead of manual generation +4. Consider using [auto-generate on content update](/webtools/addons/sitemap/configuration/auto-generate) for incremental updates + +See [Configuration: Limit](/webtools/addons/sitemap/configuration/limit) for details on managing large sitemaps. + +--- + +## Still Having Issues? + +1. **Check server logs** for detailed error messages +2. **Restart Strapi** after configuration changes +3. **Clear browser cache** if UI behaves unexpectedly +4. **Verify permissions** are correctly set (see [API Permissions](/webtools/addons/sitemap/api-permissions)) + +If problems persist, check the [GitHub issues](https://github.com/pluginpal/strapi-webtools/issues) or create a new issue with: +- Strapi version +- Webtools version +- Sitemap addon version +- Error messages from server logs +- Steps to reproduce the issue diff --git a/packages/docs/docs/addons/sitemap/getting-started/usage.md b/packages/docs/docs/addons/sitemap/getting-started/usage.md index 44128440..634903a1 100644 --- a/packages/docs/docs/addons/sitemap/getting-started/usage.md +++ b/packages/docs/docs/addons/sitemap/getting-started/usage.md @@ -19,10 +19,10 @@ An URL bundle is a set of URLs grouped by type. If you set up an URL bundle, all URLs coming from a URL bundle will get the following XML attributes: -- `` -- `` -- `` -- `` +- `` - The URL location +- `` - Last modification date (automatically set from Strapi) +- `` - Relative importance (0.1 - 1.0) +- `` - How often search engines should crawl +### Bundle Settings + +When configuring a URL bundle, you can set: + +| Setting | Options | Description | +|---------|---------|-------------| +| **Priority** | `0.1` - `1.0` | Relative importance of URLs in this bundle. Higher priority (e.g., `0.8` or `1.0`) suggests these URLs are more important. Default is typically `0.5`. | +| **Change frequency** | `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, `never` | Hint to search engines about how often these URLs change. Does not guarantee crawl frequency. | + +:::tip Multiple Bundles +You can add the same content type multiple times with different settings. For example: +- **Bundle 1**: English articles with `daily` updates and `priority: 0.8` +- **Bundle 2**: Dutch articles with `weekly` updates and `priority: 0.6` + +This allows fine-grained control over how different content and locales appear in your sitemap. +::: + ## Custom URLs A custom URL is meant to add URLs to the sitemap which are not managed in Strapi. It might be that you have custom route like `/account` that is hardcoded in your front-end. If you'd want to add such a route (URL) to the sitemap you can add it as a custom URL. diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index 7e1411d7..395598ad 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -120,6 +120,7 @@ const sidebars = { "addons/sitemap/getting-started/cli", "addons/sitemap/getting-started/api-permissions", "addons/sitemap/getting-started/admin-permissions", + "addons/sitemap/getting-started/troubleshooting", ], }, { From 55c61ee648c6491209e11852d7c0bd12a7737b18 Mon Sep 17 00:00:00 2001 From: Mathijs Schouten <35879908+MSACC@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:21:53 +0100 Subject: [PATCH 29/29] Fix (broken) links to pages --- packages/docs/docs/addons/redirects/api/rest.md | 2 +- packages/docs/docs/api/rest.md | 2 +- packages/docs/docs/getting-started/installation.md | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/docs/docs/addons/redirects/api/rest.md b/packages/docs/docs/addons/redirects/api/rest.md index cc49e05a..87b993e2 100644 --- a/packages/docs/docs/addons/redirects/api/rest.md +++ b/packages/docs/docs/addons/redirects/api/rest.md @@ -22,7 +22,7 @@ Before you can use the redirects endpoint publicly, you need to configure the ** **Quick Setup in Settings > Users & Permissions > Roles > Public:** - `webtools-addon-redirects.redirect.find` -For detailed permission configuration including admin panel access, see the [Permissions documentation](/webtools/addons/redirects/permissions). +For detailed permission configuration including API tokens and admin panel access, see the [API Permissions](/webtools/addons/redirects/api-permissions) and [Admin Permissions](/webtools/addons/redirects/admin-permissions) documentation. ::: diff --git a/packages/docs/docs/api/rest.md b/packages/docs/docs/api/rest.md index 6cad3da6..d39bd8ea 100644 --- a/packages/docs/docs/api/rest.md +++ b/packages/docs/docs/api/rest.md @@ -24,7 +24,7 @@ Before you can use the router and url-alias endpoints publicly, you need to conf - `webtools.router.find` - For each enabled content type: `[content-type].find` -See the complete [Permissions Guide](/permissions) for detailed instructions on all three permission levels. +See the [API Permissions](/api-permissions) guide for detailed instructions on setting up permissions, including API tokens and content-type permissions. ::: ## Router diff --git a/packages/docs/docs/getting-started/installation.md b/packages/docs/docs/getting-started/installation.md index 90cdab9a..d8d35f31 100644 --- a/packages/docs/docs/getting-started/installation.md +++ b/packages/docs/docs/getting-started/installation.md @@ -73,7 +73,8 @@ After successful installation you have to rebuild the admin UI so it'll include ### Post-install checklist - Enable Webtools per content type → see [Usage](/webtools/usage) -- Review Roles & Permissions → see [Permissions](/webtools/permissions) +- Review API Permissions → see [API Permissions](/webtools/api-permissions) +- Review Admin Panel Permissions → see [Admin Permissions](/webtools/admin-permissions) ## Updating Webtools