Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gatsby Blog starter fails frontend #38

Open
notmattmonroe opened this issue Apr 20, 2022 · 29 comments
Open

Gatsby Blog starter fails frontend #38

notmattmonroe opened this issue Apr 20, 2022 · 29 comments

Comments

@notmattmonroe
Copy link

Both approaches outlined in the doc for running the start successfully build and start the backend but fail to build the frontend.

OSX 12.1

node -v
v16.14.2

yarn -v
1.22.18

NPX output
npx.txt

YARN output
yarn.txt

The Next Blog starter works fine with either approach

@nzsg
Copy link

nzsg commented May 15, 2022

Same issue here on MacOS 12.3.1

I found 2 issues.

  1. Something in the setup doesn't seem to like localhost. Replacing localhost with 127.0.0.1 let the connection to Strapi work.

  2. After the backend builds, the frontend tries to build but there is no .env.development with the API token configured so the frontend fails.

Creating a Strapi API token and setting the API endpoint to 127.0.0.1 in .env.development got me going. Hope this helps someone.

@notmattmonroe
Copy link
Author

Yea, adding in the .env.development in the frontend project with API token resolved it. Documentation should be updated to reflect that step.

@remidej
Copy link
Contributor

remidej commented May 18, 2022

Yes the problem is that create-strapi-starter is not able to generate the API token required. It's mentioned in the readme:

You will however need to manually create a full access API token in Strapi. Once it's created, save it as STRAPI_TOKEN in your environment variables.

@connerxyz
Copy link

Adding a bit of detail here...

Attempting to use the Gatsby blog starter as documented here via npx didn't work.

The command is:
npx create-strapi-starter my-project gatsby-blog

The error produced is:

ModuleNotFoundError: Module not found: Error: Can't resolve '../../public/page
[develop:frontend]   -data/sq/d/960431041.json'...

Work around:

Here's how I was able to get it to work.

  1. Launch Strapi backend using npm run --prefix backend develop, which allowed me to create the admin initial account.

  2. With the admin panel working, create a full-access API token.

  3. Add frontend/.env.development with STRAPI_TOKEN and STRAPI_API_URL like this

STRAPI_TOKEN=5c9e945085...
STRAPI_API_URL=http://localhost:1337
  1. Then Gatsby using npm run --prefix frontend develop

My system:

  • MacOS Catalina 10.15.7
  • Node v16.13.1
  • NPX 8.1.2
  • NVM 0.33.11

@Jordan1022
Copy link

Jordan1022 commented Jun 3, 2022

My frontend is failing as well but error is a little different:
Screen Shot 2022-06-03 at 11 56 26 AM
Screen Shot 2022-06-03 at 11 57 41 AM
There are more errors similar to this one

@Jordan1022
Copy link

Scratch that. @connerxyz was right. Went the route of running BE and getting the API key etc and now I'm up and running. Thanks!

@jvmontes
Copy link

jvmontes commented Jun 7, 2022

@Jordan1022 @connerxyz I'm seeing the same issue and wasn't able to get a resolution..

I also followed the starter by running npx create-strapi-starter my-project gatsby-blog

Then I ran @connerxyz's work around and got this error below

 ERROR #11321  PLUGIN

"gatsby-source-strapi" threw an error while running the sourceNodes lifecycle:

connect ECONNREFUSED ::1:1337

  Error: connect ECONNREFUSED ::1:1337
  
  - node:net:1161 TCPConnectWrap.afterConnect [as oncomplete]
    node:net:1161:16
  
warn The gatsby-source-strapi plugin has generated no Gatsby nodes. Do you need it? This could also suggest the plugin is misconfigured.

This issue was also happening when I was simply trying to get Strapi connected to another app. I'd be very thankful for any help!

@chadwcarlson
Copy link

@jvmontes I found that the backend needs the following to get this starter to work.

  • api_token: it's mentioned above, but the token needs full-access, not read-only access.
  • permissions: the bootstrap initializes find/findOne permissions for Public users, but none for Authenticated users. So its necessary to replicate what's been set up for Public for Authenticated.

I've found that replacing backend/src/bootstrap.js with the below fixes things on first startup. It will create the API token (setInitFrontendAPIToken) and match those permissions for you (setInitPermissions), saving the token to frontend/env.development.

// backend/src/bootstrap.js

"use strict";

const fs = require("fs-extra");
const path = require("path");
const mime = require("mime-types");
const set = require("lodash.set");
const {
  categories,
  authors,
  articles,
  global,
  about,
} = require("../data/data.json");

async function isFirstRun() {
  const pluginStore = strapi.store({
    environment: strapi.config.environment,
    type: "type",
    name: "setup",
  });
  const initHasRun = await pluginStore.get({ key: "initHasRun" });
  await pluginStore.set({ key: "initHasRun", value: true });
  return !initHasRun;
}

async function setInitPermissions(roleType, newPermissions) {
  // Find the ID of the role
  const role = await strapi
    .query("plugin::users-permissions.role")
    .findOne({
      where: {
        type: roleType,
      },
    });

  // Create the new permissions and link them to the role
  const allPermissionsToCreate = [];
  Object.keys(newPermissions).map((controller) => {
    const actions = newPermissions[controller];
    const permissionsToCreate = actions.map((action) => {
      return strapi.query("plugin::users-permissions.permission").create({
        data: {
          action: `api::${controller}.${controller}.${action}`,
          role: role.id,
        },
      });
    });
    allPermissionsToCreate.push(...permissionsToCreate);
  });
  await Promise.all(allPermissionsToCreate);
}

async function setInitFrontendAPIToken(attributes) {
  const apiTokenService = strapi.service(`admin::api-token`);
  const apiToken = await apiTokenService.create(attributes);
  const accessKey = apiToken.accessKey;
  const credentialsLocation = process.env.FRONTEND_ENV_LOCATION || "frontend/.env.development"
  fs.writeFile(credentialsLocation, `STRAPI_TOKEN=${accessKey}`, function (err) {
    if (err) return console.log(err);
    console.log('Frontend .env file updated.');
  });
}

function getFileSizeInBytes(filePath) {
  const stats = fs.statSync(filePath);
  const fileSizeInBytes = stats["size"];
  return fileSizeInBytes;
}

function getFileData(fileName) {
  const filePath = path.join("data", "uploads", fileName);
  // Parse the file metadata
  const size = getFileSizeInBytes(filePath);
  const ext = fileName.split(".").pop();
  const mimeType = mime.lookup(ext);

  return {
    path: filePath,
    name: fileName,
    size,
    type: mimeType,
  };
}

async function uploadFile(file, name) {
  return strapi
    .plugin("upload")
    .service("upload")
    .upload({
      files: file,
      data: {
        fileInfo: {
          alternativeText: `An image uploaded to Strapi called ${name}`,
          caption: name,
          name,
        },
      },
    });
}

// Create an entry and attach files if there are any
async function createEntry({ model, entry }) {
  try {
    // Actually create the entry in Strapi
    await strapi.entityService.create(`api::${model}.${model}`, {
      data: entry,
    });
  } catch (error) {
    console.error({ model, entry, error });
  }
}

async function checkFileExistsBeforeUpload(files) {
  const existingFiles = [];
  const uploadedFiles = [];
  const filesCopy = [...files];

  for (const fileName of filesCopy) {
    // Check if the file already exists in Strapi
    const fileWhereName = await strapi.query("plugin::upload.file").findOne({
      where: {
        name: fileName,
      },
    });

    if (fileWhereName) {
      // File exists, don't upload it
      existingFiles.push(fileWhereName);
    } else {
      // File doesn't exist, upload it
      const fileData = getFileData(fileName);
      const fileNameNoExtension = fileName.split('.').shift()
      const [file] = await uploadFile(fileData, fileNameNoExtension);
      uploadedFiles.push(file);
    }
  }
  const allFiles = [...existingFiles, ...uploadedFiles];
  // If only one file then return only that file
  return allFiles.length === 1 ? allFiles[0] : allFiles;
}

async function updateBlocks(blocks) {
  const updatedBlocks = [];
  for (const block of blocks) {
    if (block.__component === "shared.media") {
      const uploadedFiles = await checkFileExistsBeforeUpload([block.file]);
      // Copy the block to not mutate directly
      const blockCopy = { ...block };
      // Replace the file name on the block with the actual file
      blockCopy.file = uploadedFiles;
      updatedBlocks.push(blockCopy);
    } else if (block.__component === "shared.slider") {
      // Get files already uploaded to Strapi or upload new files
      const existingAndUploadedFiles = await checkFileExistsBeforeUpload(
        block.files
      );
      // Copy the block to not mutate directly
      const blockCopy = { ...block };
      // Replace the file names on the block with the actual files
      blockCopy.files = existingAndUploadedFiles;
      // Push the updated block
      updatedBlocks.push(blockCopy);
    } else {
      // Just push the block as is
      updatedBlocks.push(block);
    }
  }

  return updatedBlocks;
}

async function importArticles() {
  for (const article of articles) {
    const cover = await checkFileExistsBeforeUpload([`${article.slug}.jpg`]);
    const updatedBlocks = await updateBlocks(article.blocks);

    await createEntry({
      model: "article",
      entry: {
        ...article,
        cover,
        blocks: updatedBlocks,
        // Make sure it's not a draft
        publishedAt: Date.now(),
      },
    });
  }
}

async function importGlobal() {
  const favicon = await checkFileExistsBeforeUpload(["favicon.png"]);
  const shareImage = await checkFileExistsBeforeUpload(["default-image.png"])
  return createEntry({
    model: "global",
    entry: {
      ...global,
      favicon,
      // Make sure it's not a draft
      publishedAt: Date.now(),
      defaultSeo: {
        ...global.defaultSeo,
        shareImage
      }
    },
  });
}

async function importAbout() {
  const updatedBlocks = await updateBlocks(about.blocks);

  await createEntry({
    model: "about",
    entry: {
      ...about,
      blocks: updatedBlocks,
      // Make sure it's not a draft
      publishedAt: Date.now(),
    },
  });
}

async function importCategories() {
  for (const category of categories) {
    await createEntry({ model: "category", entry: category });
  }
}

async function importAuthors() {
  for (const author of authors) {
    const avatar = await checkFileExistsBeforeUpload([author.avatar]);

    await createEntry({
      model: "author",
      entry: {
        ...author,
        avatar,
      },
    });
  }
}

async function importSeedData() {

  // Initial demo permissions.
  const initPermissions = {
    article: ["find", "findOne"],
    category: ["find", "findOne"],
    author: ["find", "findOne"],
    global: ["find", "findOne"],
    about: ["find", "findOne"],
  }

  // Initialize public permissions.
  await setInitPermissions("public", initPermissions)

  // Initialize authenticated permissions.
  await setInitPermissions("authenticated", initPermissions)

  // Creating initial demo API token for the frontend.
  await setInitFrontendAPIToken({
    type: 'full-access',
    name: 'full-access-demo',
    description: 'Initial frontend demo token'
  })

  // Create all entries
  await importCategories();
  await importAuthors();
  await importArticles();
  await importGlobal();
  await importAbout();
}

module.exports = async () => {
  const shouldImportSeedData = await isFirstRun();

  if (shouldImportSeedData) {
    try {
      console.log("Setting up the template...");
      await importSeedData();
      console.log("Ready to go");
    } catch (error) {
      console.log("Could not import seed data");
      console.error(error);
    }
  }
};

@jvmontes
Copy link

@chadwcarlson thank you!

So, here's what I had to do to get my app up and running.

Follow @connerxyz 's work around. Before hitting step 4:

npm run --prefix frontend develop

I follow @chadwcarlson lead and replace backend/src/bootstrap.js with his update.

Thanks, finally can see the blog welcome screen! Cheers

@AminSarafraz
Copy link

AminSarafraz commented Oct 4, 2022

@connerxyz workaround worked for me. If you are using yarn instead of npm, while in your main project directory, your commands will become:

yarn --cwd backend develop
yarn --cwd frontend develop

@lancesnider
Copy link

None of these have helped me. I'm using the starter out of the box, but I'm still getting:

Error: connect ECONNREFUSED ::1:1337

I've tried everything mentioned here and in other threads:

  • My Public/Authenticated settings are all correct.
  • I've tried various versions of node
  • I've tried using @chadwcarlson's bootstrap
  • I've tried with npm and yarn
  • I had a coworker try it to see if it was funky settings on my computer
  • I've removed the repo and re-cloned it from scratch
  • I've deleted and generated new keys

I'm feeling pretty stuck at this point.

@red1
Copy link

red1 commented Jan 24, 2023

I've the same issues guys,
So I generated a full access token, and updated my strapi endpoint url to

STRAPI_TOKEN=128b964c... a9109424
STRAPI_API_URL=http://localhost:1337

Now i'm not anymore stuck on the 403 but I've got the following error


 ERROR #85923  GRAPHQL

There was an error in your GraphQL query:

Cannot query field "strapiGlobal" on type "Query".

If you don't expect "strapiGlobal" to exist on the type "Query" it is most likely a typo. However, if you expect "strapiGlobal" to exist there are
 a couple of solutions to common problems:

- If you added a new data source and/or changed something inside gatsby-node/gatsby-config, please try a restart of your development server.
- You want to optionally use your field "strapiGlobal" and right now it is not used anywhere.

It is recommended to explicitly type your GraphQL schema if you want to use optional fields.

File: src/components/seo.js:8:7

See our docs page for more info on this error: https://gatsby.dev/creating-type-definitions

for all templates of the starter kit : about.js, ...
Is this starter code really supposed to work ?

@red1
Copy link

red1 commented Jan 24, 2023

nevermind I found the issue when I looked at the global api -> 404 : http://localhost:1337/api/global
So I looked and found the site to configure in the admin UI : http://localhost:1337/admin/content-manager/singleType/api::global.global and the about stuff as well

@hoseindoran
Copy link

I've the same issues guys, So I generated a full access token, and updated my strapi endpoint url to

STRAPI_TOKEN=128b964c... a9109424
STRAPI_API_URL=http://localhost:1337

Now i'm not anymore stuck on the 403 but I've got the following error


 ERROR #85923  GRAPHQL

There was an error in your GraphQL query:

Cannot query field "strapiGlobal" on type "Query".

If you don't expect "strapiGlobal" to exist on the type "Query" it is most likely a typo. However, if you expect "strapiGlobal" to exist there are
 a couple of solutions to common problems:

- If you added a new data source and/or changed something inside gatsby-node/gatsby-config, please try a restart of your development server.
- You want to optionally use your field "strapiGlobal" and right now it is not used anywhere.

It is recommended to explicitly type your GraphQL schema if you want to use optional fields.

File: src/components/seo.js:8:7

See our docs page for more info on this error: https://gatsby.dev/creating-type-definitions

for all templates of the starter kit : about.js, ... Is this starter code really supposed to work ?

I have the same issue
I generate a full access token API, but I got error
what should I do?

@lancesnider
Copy link

lancesnider commented Jan 29, 2023

3 of us spent a week on this issue with no luck. In the end we went with Contenful. :( Too bad because Strapi seemed to fit our needs better.

@hoseindoran
Copy link

I want use strapi in my project :(
I tested all of solutions above, but did not fix. I don't know doing really

@lancesnider
Copy link

I want use strapi in my project :( I tested all of solutions above, but did not fix. I don't know doing really

I don't think the problem is you. 🤷

@red1
Copy link

red1 commented Jan 30, 2023 via email

@hoseindoran
Copy link

Global is in the single types category, its fill by default

@lancesnider
Copy link

I filled mine as well.

@nullRefErr
Copy link

Adding a bit of detail here...

Attempting to use the Gatsby blog starter as documented here via npx didn't work.

The command is: npx create-strapi-starter my-project gatsby-blog

The error produced is:

ModuleNotFoundError: Module not found: Error: Can't resolve '../../public/page
[develop:frontend]   -data/sq/d/960431041.json'...

Work around:

Here's how I was able to get it to work.

  1. Launch Strapi backend using npm run --prefix backend develop, which allowed me to create the admin initial account.
  2. With the admin panel working, create a full-access API token.
  3. Add frontend/.env.development with STRAPI_TOKEN and STRAPI_API_URL like this
STRAPI_TOKEN=5c9e945085...
STRAPI_API_URL=http://localhost:1337
  1. Then Gatsby using npm run --prefix frontend develop

My system:

  • MacOS Catalina 10.15.7
  • Node v16.13.1
  • NPX 8.1.2
  • NVM 0.33.11

fixed my issue

@hoseindoran
Copy link

I filled mine as well.

I downgrade strapi version to 4.0.0 then its worked for me

@Alex-Van-Dijck
Copy link

I keep getting

GraphQLError: Unknown type "STRAPI__COMPONENT_SHARED_MEDIA". Did you mean "STRAPI__COMPONENT_SH
ARED_SEO", "STRAPI__COMPONENT_SHARED_QUOTE", "STRAPI__COMPONENT_SHARED_SEOEdge", "STRAPI__COMPO
NENT_SHARED_SLIDER", or "STRAPI__COMPONENT_SHARED_QUOTEEdge"?

upon executing my page query's but can't seem to find the cause.

@devsWecreate
Copy link

@Alex-Van-Dijck I am having the same error, any progress?

@Alex-Van-Dijck
Copy link

@Alex-Van-Dijck I am having the same error, any progress?

Yes, had to work with another blog template without strapi sad enough.

@devsWecreate
Copy link

@Alex-Van-Dijck thank you for your quick feedback. Yes very sad. Normally we use Gatsby/Strapi or WP or Laravel, without GraphQl, with Rest API, I wanted to jump to GraphQL, but only it is giving a problems, so sad.

@devsWecreate
Copy link

devsWecreate commented Mar 30, 2023

@Alex-Van-Dijck I fixed, and it works for me
in the about.js file,

const { strapiAbout } = useStaticQuery(graphqlquery { strapiAbout { title blocks { ...Blocks } } })

Change about for strapiAbout

@ionurboz
Copy link

03.17.2024 and we haven't any solution?

@red1
Copy link

red1 commented Mar 17, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet