Giter Site home page Giter Site logo

strapi-plugin-seo's Introduction

Strapi plugin SEO

The official plugin to make your Strapi content SEO friendly

Features

  • Easily see which Content-Types does have the SEO component or not.
  • Manage the important tags for your SEO (metatitle, metadescription) and preview your content in the SERP
  • Manage your meta social tags (Facebook & Twitter) and preview your post.
  • Strong SEO analysis for your content.

Installation

To install this plugin, you need to add an NPM dependency to your Strapi application.

# Using Yarn
yarn add @strapi/plugin-seo

# Or using NPM
npm install @strapi/plugin-seo

How it works

When clicking on the plugin homepage for the first time, the plugin will automatically look if a shared.seo component exists in your project. If not, the plugin will automatically create it with a sub shared.meta-social component.

If a shared.seo component already exists in your project. You might want to rename it or delete it otherwise, the plugin will not create the necessary component in order to work.

Homepage

From there you can get an overview of which content-types contains the SEO component or not. You can quickly add the SEO component to a selected content-type.

Note: By doing this, you will be redirected to the Content-Types builder on the specific content-type. You'll need to create a new component at the root of this content-type called seo using the existing component the plugin created for you: shared.seo.

Content Manager

From any content manager view for a content-type that contains the SEO component, you'll be able to see a right-side card dedicated for the SEO plugin. From there you can see a quick SEO analysis and action for you to perform (opening preview, opening complete analysis details modal).

Note: You'll need to fill your SEO component with data to be able to see the SERP preview, Social post preview and complete analysis.

Configuration

./config/plugins.js

module.exports = ({ env }) => ({
  // ...
  seo: {
    enabled: true,
  },
  // ...
});

Then, you'll need to build your admin panel:

# Using Yarn
yarn build

# Or using NPM
npm run build

SEO settings page

You'll be able from the SEO settings page to import a shared.seo & shared.meta-social components from any GitHub repository By default, our components GitHub repository is being used.

Notice: If you decide to import your own components, make sure that they belong to a shared category that their names is the same (seo, meta-social). Notice2: When adding your SEO component, make sure to name it 'seo' and to include it in the root of your Content-Type.

EditView SEO button

Once you create your SEO component in the edit view inside the Content Manager, the SEO button will appear on the the right-links injection zone. You'll be able to:

  • Manage the meta title & description of your content and preview it in SERP.
  • Manage your meta social tags (Facebook & Twitter) and preview your post.
  • Analyze your content a little deeper via an SEO analysis of your content.

strapi-plugin-seo's People

Contributors

binabh avatar dgrebb avatar innerdvations avatar luchopenafiel avatar mattiebelt avatar mcastres avatar ramiromonte avatar rumbleperson avatar sjoukedv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

strapi-plugin-seo's Issues

Helpful feature request character count on fields

Hey Guys loving the new plugin you have built. I just need to know if you could add to the roadmap the character count when the line is too long.

So for example when i type in description for meta social and the length of characters are say 75 and only 65 are allowed i get this message: "The value is too long."

Could it instead say "The value is too long you have 75 characters (65 Max)."

This would be super helpful or even have character count as I type in the field would be even better!

Keep up to great work guys!

Is this for strapi v4 only?

Hi, trying to install on strapi v3.6, I get no errors but nothing shows up in admin. Am I missing something?

SEO analysis and preview not working

We have installed the seo plugin according to the documentation. Inserted info into the meta title, description, and keywords but the analysis and preview aren't registering. Please help. FireShot Capture 045 - Content Manager - dev costnip org

social preview is not working as I expected

Hi !

If I use the "Social Preview" button without adding an image to my metasocial.*.image field, the social preview states :

Notice : Complete your social component to see the preview

As the image field is optional in the metasocial component, I expect the preview to fallback to the required seo.metaImage field.

Is it a bug or it is the correct behaviour ?

Thanks

Provide guidance for the `metaRobots` field

Right now, when you add the SEO component, you are presented with a bunch of fields with no descriptions. For most fields, it's not a big deal, but the metaRobots fields leaves me completely baffled as to what values it might expect. I've seen in another issue thread that you can use this field to prevent indexing by writing noindex, but I find myself scratching my head as to the exact syntax of how to write it, commas, spaces, quotes, etc.

Could you please provide a description that explains the syntax of this field (maybe with a link to a more detailed explanation) and a useful placeholder to get a feel for the syntax quickly?

Adding seo component to single type causes error in Content-Manager

Description

When seo component is added to a single type (non repeatable) it throws an error TypeError: zn.split is not a function in Content Manager when trying to edit the said type. The page is blank and said single type can not be edited.
When seo component is removed error is no longer present and single type is now editable from Content Manager.
seo component on collection type is working as intended.

Strapi version: 4.4.3
strapi-plugin-seo version: 1.7.5
node version: 16.14.2

Single Type schema.json (generated from strapi Content Type builder):

{
  "kind": "singleType",
  "collectionName": "homepages",
  "info": {
    "singularName": "homepage",
    "pluralName": "homepages",
    "displayName": "Homepage",
    "description": ""
  },
  "options": {
    "draftAndPublish": true
  },
  "pluginOptions": {},
  "attributes": {
    "hero": {
      "displayName": "hero",
      "type": "component",
      "repeatable": false,
      "component": "page.hero"
    },
    "section": {
      "displayName": "section",
      "type": "component",
      "repeatable": true,
      "component": "page.section"
    },
    "seo": {
      "type": "component",
      "repeatable": false,
      "component": "shared.seo"
    }
  }
}

Error

TypeError: zn.split is not a function
    at xt (main.240719f9.js:15047:4327)
    at At (main.240719f9.js:15048:148)
    at main.240719f9.js:15050:1711
    at Array.map (<anonymous>)
    at main.240719f9.js:15050:1663
    at Array.map (<anonymous>)
    at jn (main.240719f9.js:15050:1023)
    at Bi (main.240719f9.js:15050:17020)
    at main.240719f9.js:15050:18382
    at tf (main.240719f9.js:16531:7084)
tc	@	main.240719f9.js:16529

Steps to reproduce

  1. Create a simple single type from strapi Content Builder
  2. Add a seo component
  3. Edit single type in Content Manager, fill out random fileds
  4. Leave all seo fields blank
  5. Save Draft
  6. Navigate away
  7. Try to edit again
  8. Error is thrown in DevTools

Plugin not working

Issue:
On plugins page, I can see "SEO" plugin listed, but it's not working

  1. Plugin is not showing it's button in the sidebar
  2. Plugin's homepage URL http://localhost:1337/admin/plugins/seo is not working
    (that may be incorrect URL, I just guessed it by other plugin's homepage URLs)

Steps to reproduce:

  • @strapi/strapi v4.5.5
  • @strapi/plugin-seo v1.7.7
  • npm package installed as dependency
  • configuration added in ./config/plugins.js
  • shared.seo component not existing

Would appreciate any help.
Steps from this issue didn't help.

Bug: Strapi 4.11.x: Crash when Switching Content Manager Pages

Today i upgraded from strapi 4.6.x to 4.11.2.

Before the upgrade everything worked fine.
Now when i open any type, the following crash appears when switching content manager pages:

image

We only have the SEO Plugin installed and according to some other tickets in this and the official strapi repo, i'm assuming it's related to the SEO Plugin

Feature request: Prefill the seo fields based on the fields of the page

Feature request

Summary

It would be nice to have the seo fields be prefilled based on the data of the page. So for example the seo title would be prefilled based on the actual title of the page.

Why is it needed?

Because the page title and seo title will often be the same. So it makes sense that you would have to input it just once instead of twice. This also makes it easier to update the title in the future. As you would only have to update it once.

Suggested solution(s)

Have an interface on the settings page of the plugin where you can set how the fields should be built up.
So for example for the seo title I can select the title field of the content type to have that be used to prefill the seo title.

It would also be cool if we can inject some extra text. So my seo title could be build up by giving the plugin a string like Strapi | [title] where [title] will be replaced by the actual title of the page.

Related issue(s)/PR(s)

None that I know of.

Feature request: allow disabling of checks via configuration

Feature request

Summary

Add the ability to enable/disable different SEO checks for collections through plugin configuration

Why is it needed?

Not every SEO check is relevant to all collections. For example, the rich text check isn't necessary on a collection that doesn't support rich text in the first place, but it will always appear as failed on the admin UI. This can be very confusing to content managers. Another example is when some base SEO is set elsewhere in the system for the content, such as socials being set site-wide, so checking against them on a per-collection basis is not necessary.

Suggested solution(s)

Allow the configuration to specify which checks are active, either plugin-wide or by content type. Something like this could work in the plugins.js file:

seo: {
    enabled: true,
    config: {
      disabled: ['meta-social-twitter'],
      contentTypes: [
        {
          uid: 'api::my-collection.collection',
          disabled: ['word-counter', 'json-structured-data']
        }
      ],
    },
  }

This would then disable those checks on that collection's edit page.

Related issue(s)/PR(s)

N/A

This plugin breaks Strapi v4.11.0

This plugin is broken in the latest Strapi version (v4.11.0) that uses React18. The error that is triggered is caused by the wrong implementation of an async function in some useEffect hooks.

The issue will be resolved by merging #40

[BUG] SEO plugin incompatible with Strapi 5

I'm checking the new Strapi version and this plugin is one of the most important plugins for landing pages and cooperative websites.

I ran the project and I got this issue:


  You can mark the path "@strapi/design-system/Box" as external to exclude it from the bundle, which
  will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Icon"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:6:21:
      6 │ import { Icon } from '@strapi/design-system/Icon';
        ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Icon" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Icon/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Icon/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:6:48:
      6 │ import { Icon } from '@strapi/design-system/Icon';
        │                                                 ^
        ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Icon" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Flex"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/KeywordDensityCheck/index.js:6:21:
      6 │ import { Flex } from '@strapi/design-system/Flex';
        ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Flex" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Flex/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Flex/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/KeywordDensityCheck/index.js:6:48:
      6 │ import { Flex } from '@strapi/design-system/Flex';
        │                                                 ^
        ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Flex" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/LastUpdatedAtCheck/index.js:8:27:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/LastUpdatedAtCheck/index.js:8:60:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Box"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:3:20:
      3 │ import { Box } from '@strapi/design-system/Box';
        ╵                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Box" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Box/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Box/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:3:46:
      3 │ import { Box } from '@strapi/design-system/Box';
        │                                               ^
        ╵                                               /index.js

  You can mark the path "@strapi/design-system/Box" as external to exclude it from the bundle, which
  will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaDescriptionCheck/index.js:9:22:
      9 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaDescriptionCheck/index.js:9:50:
      9 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:7:22:
      7 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:7:50:
      7 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/CanonicalUrlCheck/index.js:9:27:
      9 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/CanonicalUrlCheck/index.js:9:60:
      9 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/WordCountCheck/index.js:9:27:
      9 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/WordCountCheck/index.js:9:60:
      9 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Badge"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/KeywordDensityCheck/index.js:7:22:
      7 │ import { Badge } from '@strapi/design-system/Badge';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Badge" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Badge/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Badge/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/KeywordDensityCheck/index.js:7:50:
      7 │ import { Badge } from '@strapi/design-system/Badge';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Badge" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Badge"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaSocialCheck/index.js:9:22:
      9 │ import { Badge } from '@strapi/design-system/Badge';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Badge" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Badge/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Badge/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaSocialCheck/index.js:9:50:
      9 │ import { Badge } from '@strapi/design-system/Badge';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Badge" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Icon"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:5:21:
      5 │ import { Icon } from '@strapi/design-system/Icon';
        ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Icon" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Icon/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Icon/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:5:48:
      5 │ import { Icon } from '@strapi/design-system/Icon';
        │                                                 ^
        ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Icon" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/helper-plugin"

    node_modules/@strapi/plugin-seo/admin/src/components/HomePage/Main/SettingsModal/index.js:23:44:
      23 │ import { ContentBox, useNotification } from '@strapi/helper-plugin';
         ╵                                             ~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "@strapi/helper-plugin" as external to exclude it from the bundle, which
  will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaTitleCheck/index.js:9:22:
      9 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaTitleCheck/index.js:9:50:
      9 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] The JSX syntax extension is not currently enabled

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:28:4:
      28 │     <AccordionGroup>
         ╵     ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able
  to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:6:22:
      6 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:6:50:
      6 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaDescriptionCheck/index.js:11:27:
      11 │ import { Typography } from '@strapi/design-system/Typography';
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaDescriptionCheck/index.js:11:60:
      11 │ import { Typography } from '@strapi/design-system/Typography';
         │                                                             ^
         ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Flex"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaSocialCheck/index.js:10:21:
      10 │ import { Flex } from '@strapi/design-system/Flex';
         ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Flex" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Flex/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Flex/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaSocialCheck/index.js:10:48:
      10 │ import { Flex } from '@strapi/design-system/Flex';
         │                                                 ^
         ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Flex" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Icon"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:5:21:
      5 │ import { Icon } from '@strapi/design-system/Icon';
        ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Icon" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Icon/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Icon/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:5:48:
      5 │ import { Icon } from '@strapi/design-system/Icon';
        │                                                 ^
        ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Icon" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Flex"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:4:21:
      4 │ import { Flex } from '@strapi/design-system/Flex';
        ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Flex" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Flex/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Flex/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:4:48:
      4 │ import { Flex } from '@strapi/design-system/Flex';
        │                                                 ^
        ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Flex" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:8:27:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:8:60:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Icon"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:10:21:
      10 │ import { Icon } from '@strapi/design-system/Icon';
         ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Icon" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Icon/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Icon/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:10:48:
      10 │ import { Icon } from '@strapi/design-system/Icon';
         │                                                 ^
         ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Icon" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:7:27:
      7 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.js:7:60:
      7 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaTitleCheck/index.js:11:27:
      11 │ import { Typography } from '@strapi/design-system/Typography';
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaTitleCheck/index.js:11:60:
      11 │ import { Typography } from '@strapi/design-system/Typography';
         │                                                             ^
         ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:5:22:
      5 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:5:50:
      5 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Accordion"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:8:7:
      8 │ } from '@strapi/design-system/Accordion';
        ╵        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Accordion" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Accordion/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Accordion/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:8:39:
      8 │ } from '@strapi/design-system/Accordion';
        │                                        ^
        ╵                                        /index.js

  You can mark the path "@strapi/design-system/Accordion" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:7:22:
      7 │ import { Stack } from '@strapi/design-system/Stack';
        ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:7:50:
      7 │ import { Stack } from '@strapi/design-system/Stack';
        │                                                   ^
        ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Box"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:10:20:
      10 │ import { Box } from '@strapi/design-system/Box';
         ╵                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Box" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Box/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Box/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:10:46:
      10 │ import { Box } from '@strapi/design-system/Box';
         │                                               ^
         ╵                                               /index.js

  You can mark the path "@strapi/design-system/Box" as external to exclude it from the bundle, which
  will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Stack"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:11:22:
      11 │ import { Stack } from '@strapi/design-system/Stack';
         ╵                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Stack" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Stack/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Stack/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:11:50:
      11 │ import { Stack } from '@strapi/design-system/Stack';
         │                                                   ^
         ╵                                                   /index.js

  You can mark the path "@strapi/design-system/Stack" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Tabs"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:6:25:
      6 │ import { TabPanel } from '@strapi/design-system/Tabs';
        ╵                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Tabs" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Tabs/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Tabs/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:6:52:
      6 │ import { TabPanel } from '@strapi/design-system/Tabs';
        │                                                     ^
        ╵                                                     /index.js

  You can mark the path "@strapi/design-system/Tabs" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:8:27:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.js:8:60:
      8 │ import { Typography } from '@strapi/design-system/Typography';
        │                                                             ^
        ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Icon"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:11:21:
      11 │ import { Icon } from '@strapi/design-system/Icon';
         ╵                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Icon" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Icon/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Icon/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:11:48:
      11 │ import { Icon } from '@strapi/design-system/Icon';
         │                                                 ^
         ╵                                                 /index.js

  You can mark the path "@strapi/design-system/Icon" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:12:27:
      12 │ import { Typography } from '@strapi/design-system/Typography';
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.js:12:60:
      12 │ import { Typography } from '@strapi/design-system/Typography';
         │                                                             ^
         ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Divider"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:7:24:
      7 │ import { Divider } from '@strapi/design-system/Divider';
        ╵                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Divider" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Divider/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Divider/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TabContent/index.js:7:54:
      7 │ import { Divider } from '@strapi/design-system/Divider';
        │                                                       ^
        ╵                                                       /index.js

  You can mark the path "@strapi/design-system/Divider" as external to exclude it from the bundle,
  which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@strapi/design-system/Typography"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:12:27:
      12 │ import { Typography } from '@strapi/design-system/Typography';
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/Typography" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/Typography/index.js" to get the file
  "node_modules/@strapi/design-system/dist/Typography/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:12:60:
      12 │ import { Typography } from '@strapi/design-system/Typography';
         │                                                             ^
         ╵                                                             /index.js

  You can mark the path "@strapi/design-system/Typography" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] The JSX syntax extension is not currently enabled

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/FacebookPreview/index.js:10:4:
      10 │     <div className="box-right snipcss-9tU8S snip-div">
         ╵     ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able
  to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.

✘ [ERROR] The JSX syntax extension is not currently enabled

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/Summary/SocialPreview/TwitterPreview/index.js:10:4:
      10 │     <div className="box-right snipcss-lxedG snip-div">
         ╵     ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able
  to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.

✘ [ERROR] Could not resolve "@strapi/design-system/IconButton"

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:13:27:
      13 │ import { IconButton } from '@strapi/design-system/IconButton';
         ╵                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Importing the directory "./dist/IconButton" is forbidden by this package:

    node_modules/@strapi/design-system/package.json:23:11:
      23 │     "./*": "./dist/*"
         ╵            ~~~~~~~~~~

  The presence of "exports" here makes importing a directory forbidden:

    node_modules/@strapi/design-system/package.json:9:2:
      9 │   "exports": {
        ╵   ~~~~~~~~~

  Import from "@strapi/design-system/IconButton/index.js" to get the file
  "node_modules/@strapi/design-system/dist/IconButton/index.js":

    node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.js:13:60:
      13 │ import { IconButton } from '@strapi/design-system/IconButton';
         │                                                             ^
         ╵                                                             /index.js

  You can mark the path "@strapi/design-system/IconButton" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

21:31:56 [vite] error while updating dependencies:
Error: Build failed with 126 errors:
node_modules/@strapi/plugin-seo/admin/src/api/settings/index.js:1:24: ERROR: Could not resolve "@strapi/helper-plugin"
node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:5:20: ERROR: Could not resolve "@strapi/design-system/Box"
node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:6:21: ERROR: Could not resolve "@strapi/design-system/Icon"
node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:7:22: ERROR: Could not resolve "@strapi/design-system/Stack"
node_modules/@strapi/plugin-seo/admin/src/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.js:8:27: ERROR: Could not resolve "@strapi/design-system/Typography"
...
    at failureErrorWithLog (/home/luisalaguna/Projects/experiments/portfolio/node_modules/vite/node_modules/esbuild/lib/main.js:1651:15)
    at /home/luisalaguna/Projects/experiments/portfolio/node_modules/vite/node_modules/esbuild/lib/main.js:1059:25
    at /home/luisalaguna/Projects/experiments/portfolio/node_modules/vite/node_modules/esbuild/lib/main.js:1527:9
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

How can we fix this?

Why is `metaImage` required?

The seo component comes with a required field metaImage, why is it required? It is not always the user has a relevant image for a page, but would like to set all the other fields. So I would suggest if the metaImage field would not be required

Also what is it exactly the metaImage field should do? Should it act as a fallback if no image is set on meta socials?

This issue is related to Oak-Digital/nextjs-strapi-plugin-seo#2

is metaImage missing in api?

I have set up a demo installation and filled the seo meta fields but when I call the endpoint with:

api.example.com/api/articles?populate=*

I get:

...
"SEO": {
"id": 1,
"metaTitle": "Meta title",
"metaDescription": "Lorem ipsum dolor sit amet fusce nostrum onvallis nihil dui iusto perspiciatis occaecat",
"keywords": "key1, key2, key3",
"metaRobots": "follow",
"structuredData": null,
"metaViewport": null,
"canonicalURL": null
}
...

and image is missing.

I'm sure I have added it to my article:
Screenshot 2023-10-05 alle 14 44 45

[feature] Autofill certain fields based on existing data

Given the way Strapi is structured this seems infeasible for now, but I think it would be really nice if you could associate certain fields on a per content-type basis with certain fields in the SEO Component (or Components more generally)

Take e.g. the default Article content type below: wouldn't it be nice if the SEO Components preloaded the Title & Description fields as metaTitle and metaDescription?

image

Plugin not showing on sidebar

I did all steps on installation but the plugin just won't show up on the sidebar.

Strapi v4.3.8

  1. Install with npm npm install @strapi/plugin-seo
  // ...
  "dependencies": {
    "@strapi/plugin-seo": "^1.7.7",
  },
  // ...
  1. Modified ./config/plugins.js to enable it
module.exports = ({ env }) => {
  const ProdConfig = { 
  // ...
  }
  
  // there is nothing else in DevConfig, just this:
  const DevConfig = { 
    seo: {
      enabled: true,
    },
  }; 

  return {
    connection: env('NODE_ENV') === 'production' ? ProdConfig : DevConfig,
  };
};

  1. Ran the build commands
npm run build
npm run dev

I get always "Your 1st level Richtext contents have less than 300 words."

Hi all I installed the plugin as documented and used it on a content type Post that had created previously.

This one contains text and content(RichText).

How can I configure your plugin to understand that the words should be calculated under content field of the post?

Right now it shows always 1 word and error "Your 1st level Richtext contents have less than 300 words."

Cannot read properties of undefined (reading 'seoChecks')

After upgrading to the latest strapi version ("^4.11.3") and latest seo-plugin version ("^1.9.2"), errors are flooding the console.

  1. When navigating between Strapi pages:
  • TypeError: Cannot read properties of undefined (reading 'seoChecks')
  1. When navigating to content-type builder and plugins/seo page page becomes blank and following errors appear in the console:
  • main.fcb6d057.js:1944 TypeError: S is not a function.
  • main.fcb6d057.js:1944 Uncaught TypeError: S is not a function

Issues are already mentioned in the following references:
strapi/strapi#16998
strapi/strapi#17024

Crash Strapi admin if we leave a rich text field empty where shared-seo component included in the schema

Current Behavior:

If I leave a rich text field empty and save it in any single-type or collection-type which contains a rich text and shared-seo component in the schema. It gives a blank screen and then I'm unable to open and edit that entry. It keeps showing a blank screen every time I try to open that entry.
Before saving that entry if I add an empty space (not null now). It works fine and I'm able to open and re-edit that entry.

Check this image with console error
seo-blank

Expected Behavior:

I should be able to view and edit a rich text field even If I leave it as null while saving it.

Steps To Reproduce:

  1. Create a new strapi project using npx create-strapi-app@latest my-project --quickstart
  2. Install strapi seo plugin following this page https://strapi.io/marketplace/plugins/@strapi-plugin-seo
  3. Run strapi project and open strapi admin panel
  4. Go to Content-Type Builder > Create new collection type
  5. Add a Rich Text field and a component shared-seo in the newly created collection type schema
  6. Now goto Content Manager and add new entry for newly created collection
  7. While adding new entry if left rich text field empty and saved the entry (null). You will get a blank screen like the attached image.
  8. But if you add some text in rich text even an empty space. You will not get any blank screen and you will be able to re-open and re-edit that entry.

Could not load js config file /srv/app/node_modules/@strapi/plugin-upload/strapi-server.js:

After the installation of the Strapi-SEO plugin and after a build ofcourse (Executed commands under here),

yarn add @strapi/plugin-seo
yarn build

I was greeted with the following message on start:

Starting your app (with develop)...
[2022-06-21 11:39:54.429] debug: ⛔️ Server wasn't able to start properly.
[2022-06-21 11:39:54.430] error: Could not load js config file /srv/app/node_modules/@strapi/plugin-upload/strapi-server.js: 
Something went wrong installing the "sharp" module

Cannot find module '../build/Release/sharp-linux-x64.node'

Require stack:
- /srv/app/node_modules/sharp/lib/sharp.js
- /srv/app/node_modules/sharp/lib/constructor.js
- /srv/app/node_modules/sharp/lib/index.js
- /srv/app/node_modules/@strapi/plugin-upload/server/services/image-manipulation.js
- /srv/app/node_modules/@strapi/plugin-upload/server/services/index.js
- /srv/app/node_modules/@strapi/plugin-upload/server/index.js
- /srv/app/node_modules/@strapi/plugin-upload/strapi-server.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/load-config-file.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/config-loader.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/index.js
- /srv/app/node_modules/@strapi/strapi/lib/commands/develop.js
- /usr/local/share/.config/yarn/global/node_modules/@strapi/strapi/bin/strapi.js


Possible solutions:
- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"
- Install for the current linux-x64 runtime: "npm install --platform=linux --arch=x64 sharp"
- Consult the installation documentation: https://sharp.pixelplumbing.com/install

Error: Could not load js config file /srv/app/node_modules/@strapi/plugin-upload/strapi-server.js: 
Something went wrong installing the "sharp" module
Cannot find module '../build/Release/sharp-linux-x64.node'

Require stack:
- /srv/app/node_modules/sharp/lib/sharp.js
- /srv/app/node_modules/sharp/lib/constructor.js
- /srv/app/node_modules/sharp/lib/index.js
- /srv/app/node_modules/@strapi/plugin-upload/server/services/image-manipulation.js
- /srv/app/node_modules/@strapi/plugin-upload/server/services/index.js
- /srv/app/node_modules/@strapi/plugin-upload/server/index.js
- /srv/app/node_modules/@strapi/plugin-upload/strapi-server.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/load-config-file.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/config-loader.js
- /srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/index.js
- /srv/app/node_modules/@strapi/strapi/lib/commands/develop.js
- /usr/local/share/.config/yarn/global/node_modules/@strapi/strapi/bin/strapi.js

Possible solutions:
- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"
- Install for the current linux-x64 runtime: "npm install --platform=linux --arch=x64 sharp"
- Consult the installation documentation: https://sharp.pixelplumbing.com/install
    at loadJsFile (/srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/load-config-file.js:18:11)
    at loadFile (/srv/app/node_modules/@strapi/strapi/lib/core/app-configuration/load-config-file.js:35:14)
    at Object.loadPlugins (/srv/app/node_modules/@strapi/strapi/lib/core/loaders/plugins/index.js:96:26)
    at async Strapi.loadPlugins (/srv/app/node_modules/@strapi/strapi/lib/Strapi.js:290:5)
    at async Promise.all (index 2)
    at async Strapi.register (/srv/app/node_modules/@strapi/strapi/lib/Strapi.js:326:5)
    at async Strapi.load (/srv/app/node_modules/@strapi/strapi/lib/Strapi.js:425:5)
    at async Strapi.start (/srv/app/node_modules/@strapi/strapi/lib/Strapi.js:169:9)

I tried installing sharp aswel, just like it mentioned.
But I just got the same issue. Even with linux and x64 declared in the package.json
Using Yarn

Impossible to fully uninstall the plugin after using it

Hi,

I used this plugins for some tests on my local project. But I realised it was not doing what I wanted.

So i deleted it from my package.json file and :

  • Removed the enable in my plugins.js file
  • Removed the two components created by the package seo and meta

But I still see the "SEO" menu item in my sidebar and also the SEO card in my edit view.

Any idea ? Did I miss something ?

Thanks for helping.

Implementation samples

Hello there!

Do you have some frontend implementation samples (with next / nuxt / etc ...) ?

SEO component should not be repeatable

image
As you can see here, it is possible to repeat the SEO component, which it does not seem to be logical, since the metadata fields are unique in most of the cases.

Why is it repeatable then?

Sometimes its create duplicate records in Database for content types.

After Enabling the Seo, Plugin for different content types. After creating the SEO content the plugin attaches the component data to multiple content types. which cases the duplicate content of the content type. After deleting from one end it will also be deleted from other components type as well. In some cases, it also attaches the same component data to the same content-type records as well.

[BUG] - special (repeated) characters are not escaped and are interpreted

I haven't tested this in multiple fields, but when adding, for example, "C++" to the keywords field, JavaScript attempts to interpret the string as code.

This may be a security concern.

Uncaught (in promise) SyntaxError: nothing to repeat

somewhere in here:

zr = (Nt, Ln) => {
  Nt.map(
    Nn => {
      if (!Z().isEmpty(Nn)) {
        const Tr = Nn.trim(),
        mr = new RegExp(Tr, 'g'),
        Nr = (Ln.join(' ').match(mr) || []).length;
        Xt[Tr] === void 0 ? Xt[Tr] = {
          count: Nr
        }
         : Xt[Tr].count += Nr
      }
    }
  )
},

Upon removing "C++" from the keywords field, the error is gone.

Happy to help debug! Not a show stopper for me, only an observation.

Image URLs in social previews are not prefixed with backend URL

In the SocialPreview (FacebookPreview and TwitterPreview) the image urls are not prefixed with the backend URL.

In our setup we have the fronted at a specific URL (example.com) and the backend / strapi sitting at a subpath (example.com/strapi). Other strapi plugins or the content manager can handle this because they use the prefixFileUrlWithBackendUrl helper function when dealing with image urls. The seo plugin however just uses the plain url and therefore the images are not shown in the preview.

I created a (not yet tested) PR: #36

[BUG] - export 'NotFound' (imported as 'NotFound') was not found in '@strapi/helper-plugin'

Hi recent version seeing this error message in console:

WARNING in ../../node_modules/@strapi/plugin-seo/admin/src/pages/App/index.js 8:375-383
export 'NotFound' (imported as 'NotFound') was not found in '@strapi/helper-plugin' (possible exports: AnErrorOccurred, AppInfoContext, AppInfoProvider, AppInfosContext, AppInfosProvider, AutoReloadOverlayBlockerContext, AutoReloadOverlayBlockerProvider, CheckPagePermissions, CheckPermissions, ConfirmDialog, ContentBox, ContentManagerEditViewDataManagerContext, CustomFieldsContext, CustomFieldsProvider, DateTimePicker, DynamicTable, EmptyBodyTable, EmptyStateLayout, FilterListURLQuery, FilterPopoverURLQuery, Form, GenericInput, GuidedTourContext, GuidedTourProvider, InjectionZone, LibraryContext, LibraryProvider, Link, LinkButton, LoadingIndicatorPage, NoContent, NoMedia, NoPermissions, NotAllowedInput, 
NotificationsContext, NotificationsProvider, OverlayBlockerContext, OverlayBlockerProvider, PageSizeURLQuery, PaginationURLQuery, RBACContext, RBACProviderContext, ReactSelect, RelativeTime, RemoveRoundedButton, SearchURLQuery, SettingsPageTitle, SortIcon, Status, StopPropagation, StrapiAppContext, StrapiAppProvider, TrackingContext, TrackingProvider, auth, contentManagementUtilRemoveFieldsFromData, difference, findMatchingPermissions, formatContentTypeData, getAPIInnerErrors, getFetchClient, getFileExtension, getOtherInfos, getType, getYupInnerErrors, hasPermissions, normalizeAPIError, onRowClick, prefixFileUrlWithBackendUrl, prefixPluginTranslations, pxToRem, request, setHexOpacity, stopPropagation, to, translatedErrors, useAPIErrorHandler, useAppInfo, useAppInfos, useAutoReloadOverlayBlocker, useCMEditViewDataManager, useCallbackRef, useCollator, useCustomFields, useFetchClient, useFilter, useFocusWhenNavigate, useGuidedTour, useLibrary, useLockScroll, useNotification, useOverlayBlocker, usePersistentState, useQuery, useQueryParams, useRBAC, useRBACProvider, useSelectionState, useStrapiApp, useTracking, wrapAxiosInstance)

SEO plugin "@strapi/plugin-seo": "1.9.1"

Autofill option?

Is there a way to autofill the title & description based on values or fallbacks? For example, I have a page which has a title "About", is there a way that the SEO title will automatically be About?

Could I also merge the site name and the page "About -- Safiro"?

meta-social component is missing in components/shared

Hi all,
Thanks for the plugin development. However, the meta-social component is missing in my Strapi.

What I did:
After install, I configured the seo component in ./config/plugins.js:
seo: {
enabled: true,
},

and thereafter I built the admin panel with yarn build.

Add component
At Strapi > SEO plugin, I added the component to the root of the Collection and Single types, named it 'seo'. Now the seo component shows up in the Content Manager. However, there're only 3 fields available:
metaTitle, metaDescription and shareImage.

seo2

Analysis modal
The analysis modal shows both the seo and the meta-social analysis but the meta-social naturally is empty.
In the Content-Type Builder, the meta-social component is missing.

I'm using:

  • Strapi v4.3.2
  • Node 16.17
  • Yarn 3.2.2
  • W11

Could anyone shed light on this?

Best regards,
Jacco

Unable to install with npm strict engine

package: v1.7.2
npm: v6.14.17
node: 16.15.0

npm install @strapi/plugin-seo --save

npm ERR! code ENOTSUP
npm ERR! notsup Unsupported engine for @strapi/[email protected]: wanted: {"node":">=12.x. <=16.x.x","npm":">=6.0.0"} (current: {"node":"16.15.0","npm":"6.14.17"})
npm ERR! notsup Not compatible with your version of node/npm: @strapi/[email protected]
npm ERR! notsup Not compatible with your version of node/npm: @strapi/[email protected]
npm ERR! notsup Required: {"node":">=12.x. <=16.x.x","npm":">=6.0.0"}
npm ERR! notsup Actual:   {"npm":"6.14.17","node":"16.15.0"}

.npmrc configuration

engine-strict=true

SEO metadata not reflected on SERP

I've installed the strapi-plugin-seo to my project, and added it to my 'Story' collection type. The seo component shows up, and I have added data for metaTitle, metaDescription, metaImage, and metaSocial. However, when I share the link to my story, or see it in a google search result, this data does not show up.

I am seeing the seo data in my endpoint for metaTitle and metaDescription, but my endpoint is not returning data for metaImage or metaSocial.

My Strapi project is hosted through Shopify, and is rendered into a Vue template.

I'm not sure what I'm doing wrong. Please advise

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.