Logo Hpv 4 Learning
Academy
Web Agency
gatsby

Come creare un blog statico usando Gatsbyjs

By Hpv4Learning 8 min18/01/2023
"Come realizzare un sito statico con il Server Side Rendering con Gatsbyjs"
Blog di cucina statico con gestionale

Troverai nel progetto

Che cosa realizzeremo in questo progetto ?

Questo sarà un progetto complesso in cui andremo a realizzare un blog di cucina fornito di un comodo gestionale realizzato in Sanity in cui potremmo editare e scrivere le nostre ricette in modo intuitivo.

Dopo aver sviluppato il nostro gestionale ci occuperemo di sviluppare il frontend della nostra applicazione in modo che sia completamente statico e servito lato server grazie a Gatsby.js.

Questo ci permetterà di ottenere:

  • Prestazioni ottimizzate.
  • Ottimizzazione lato SEO
  • Massima flessibilità nella gestione dei nostri contenuti

E per chiudere il progetto andremo a vedere nel dettaglio come utilizzare i dati strutturati per migliorare la nostra SEO.

Creare un progetto con Sanity

Chiariamo subito: Che cos'è un gestionale o Headless CMS ? Altro non è che un'applicazione dotata di un'interfaccia customizzabile che ci permette di creare, modificare e organizzare i nostri contenuti, da qua il termine di CMS o Content Managment System.

Esempio di gestionale in Sanity

Creazione del progetto e dell'account

Il primo passo è sicuramente quello di andare a creare un nuovo progetto sanity e il miglior modo è di seguire la loro guida ufficiale o lanciare il comando

npm create sanity@latest -- --template clean --create-project "Sanity Project" --dataset production 

A questo punto inizierà un breve processo che ci permetterà di creare un account Sanity e avere il nostro progetto ready to dev. Ora non ci resta che lanciare da terminale:

    cd sanity-project
    npm run dev

E il nostro progetto sarà pronto lanciato in localhost sulla porta 3333

Creare il nostro primo Schema

All'interno del nostro progetto troveremo questa struttura

    ├── README.md
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    ├── sanity.cli.js
    ├── sanity.config.js
    ├── schemas
    │   └── index.js
    └── static

All'interno della folder schema andremo a definire i nostri types e quali saranno i suoi campi.

Creiamo un file pet.js nella folder e scriviamo il seguente codice.

    export default {
      name: 'pet',
      type: 'document',
      title: 'Pet',
      fields: [
        {
          name: 'name',
          type: 'string',
          title: 'Name'
        }
      ]
     }
  • name: "pet" permette di creare e assegane un type _pet al nostro schema, in modo che sia referenziabile e collegabile ad altri schema.
  • type: document invece serve a indicare che sarà possibile creare nuovi documenti di tipo _pet.
  • title sarà il nome che nell'interfaccia grafica assegneremo a questo schema
  • fields è un'array di campi che il nostro documento conterrà.

A questo punto non ci resta che spostarci nel file index.js all'interno della folder schema

  // schemas/index.js
    import pet from './pet'

    export const schemaTypes = [pet]

e rilanciare il nostro server e avremo il nostro primo schema pronto per essere editato.

Sviluppare il nostro gestionale

Ora, il nostro gestionale sarà sicuramente più complesso e andare a crearlo passo passo sarebbe un'agonia diciamocelo, soprattutto a popolare di dati 🥱. Ma anche qua Sanity ci aiuta, perché è possibile importare i dati in modo smart.

Per prima cosa scarica le risorse necessarie per importare tutti i dati e da questa repo copiate tutto quello che trovate nella folder di schemas e incollatela nel vostro progetto.

Importante: Volendo potete tranquillamente forkarla ma ricordatevi di sostituire il file sanity.json in modo che punti al vostro progetto nel suo projectId e dataset e project.name.

Consiglio però di fare un bel copy pasta della folder schema e si vola.

Come sarà organizzato il nostro Gestionale

Avremo una struttura abbastanza prevedibile, composta da 3 tipologie di documenti differenti.

  • recipe: Le singole ricette, che avranno come campi il titolo, riassunto, immagine di copertina, lista d'ingredienti, una descrizione della ricetta e due reference. Una che punta alle categorie e una agli chef
  • categorie: Sono dei raccoglitori di ricette e hanno come campi un titolo, una descrizione e una reference che punta verso le ricette
  • chef: Ci permette di assegnare a ogni ricetta uno chef.

Importare i dati nel nostro database

A questo punto abbiamo il nostro progetto Sanity, abbiamo i nostri schema, e non ci resta che popolare il Db in modo che sia tutto funzionale.

Ora, andiamo a estrarre il nostro file zip che abbiamo scaricato e in cui troviamo due cose

  • un file backup.ndjson
  • Diverse folder contenenti immagini per ogni schema.

Ora trasciniamo nella root del nostro progetto il file backup.ndjson, apriamo il terminale, e posizioniamoci all'interno del nostro progetto prima di lanciare il comando:

npx @sanity/cli dataset import backup.ndjson production --replace

In questo modo il nostro dataset verrà popolato con tutte le ricette, categorie e informazioni. 🤗

Ora che ce ne facciamo delle immagini ? Beh, sono li come fallback di sicurezza nel caso non venissero importate durante il processo. In caso succedesse, vi basterà andare a mettere le immagini ai singoli elementi e sarà tutto ok.

Pubblicare il nostro gestionale

Ancora un ultimissimo step e il nostro gestionale in sanity sarà terminato: ovvero rendere pubbliche e accessibili le informazioni contenute al suo interno.

Per fare questo ci basterà usare il comando

npx @sanity/cli graphql deploy

Alla fine di questo processo, il vostro gestionale sarà pubblicato al link https://{projectID}.api.sanity.io/v1/graphql/{dataset}/default

Per vedere il vostro projectId vi basterà andare nel file sanity.json

Collegare un progetto Sanity a Gatsby

In questo progetto per lavorare sul frontend utilizzeremo Gatsby, che è un framework per il frontend costruito su React che ci permette di generare siti statiti.

  1. Installare gatsby-cli usando:
    npm install -g gatsby-cli
  2. Creare un nuovo progetto gatsby con il comando
    gatsby new {nome-progetto}
  3. Scegliere il linguaggio desiderato tra js o typescript
  4. Scegliere Sanity come CMS
  5. Scegliere la nostra libreria di styling preferita
  6. Scegliere come plugin aggiuntivi: responsive images, add sitemap, generate manifest, markdown support.
  7. Inserire projectId e dataset-name.

Per trovare queste due informazioni, riapriamo il nostro progetto Sanity, apriamo il file sanity.json dove troveremo.

 "api": {
    "projectId": "7rtujyv5",
    "dataset": "production"
  }

Volendo possiamo anche ottenere le informazioni dall'url https://www.sanity.io/manage/personal/project/{projectId}.

Creare pagine statiche lato server in Gatsby.

A questo punto andiamo a creare la pagine per le nostre ricette e categorie. Per la parte di styling, tema e componenti vi lascio la repo del progetto finale oppure una bella repo con uno starter con già lo style del theme e una configurazione di base già fatto

Come creare una query in gatsby

Il primo step è quello di creare un file query.ts con le nostre query in graphql e i loro rispettivi type.

In questo esempio useremo quelle delle categorie.

export const categoryQuery = `
{
    allSanityCategory {
    nodes {
      _id
      titolo
       ricettario {
        _createdAt
        _id
      }
    }
  }
}
`;

export type CategoryQueryProps = {
  data: {
    allSanityCategory: {
      nodes: {
        titolo: NonNullable<Queries.SanityCategory["titolo"]>;
        _id: NonNullable<Queries.SanityCategory["_id"]>;
        ricettario: {
          _id: NonNullable<Queries.SanityRecipe["_id"]>;
          _createdAt: NonNullable<Queries.SanityRecipe["_createdAt"]>;
        }[];
      }[];
    };
  };
};

Un paio di precisazioni. Quel

Queries
che vedete nei types è un namespace che gatsby crea e aggiorna ogni volta che andiamo a lanciare il nostro dev server e contiene tutti i types delle nostre queries.

Per quanto riguarda la nostra

categoryQuery
quello che vogliamo ottenere è un array, quindi tutti i nodi, che al suo interno contenga per ogni categoria un id, titolo e il campo ricettario.

Anche ricettario a sua volta sarà un array e lo useremo sia per controllare che una categoria abbia almeno una ricett, sia per realizzare una paginazione lato server delle pagine delle nostre categorie.

Creare una pagina con node in gatsby

Ora è tempo d'importare la nostra query sul file gatsby-node.ts. Attenzione, nel caso voleste usa javascript e non typescript dovrete usare commonjs a meno che non vi troviate almeno alla versione ^5.3 di gatsby. Usando typescript invece gli ES Modules saranno supportati.

Ma torniamo alle nostre pagine statiche. Andiamo a creare un file chiamato gatsby-node.ts in cui andiamo a importare.


import { GatsbyNode } from "gatsby";
import {
  categoryQuery,
  CategoryQueryProps,
} from "./query";
import { createSlugFromTitle } from "./src/utils";
import { resolve } from "path";

Dove createSlugFromTitle altro non è che una utils che splitta una stringa per gli spazi e la joina tutta minuscola separata da -.

Ora utilizzeremo l'API di Gastby createPages che come potete immaginare serve a creare delle pagine. Per i dettagli vi lascio la doc ufficiale.

export const createPages: GatsbyNode["createPages"] = async ({
  actions,
  graphql,
}) => {
  const { createPage } = actions;

  const allCategories = (await graphql(categoryQuery)) as CategoryQueryProps;
  const allRecipes = (await graphql(allRecipeQuery)) as AllRecipeQueryProps;

  allCategories.data.allSanityCategory.nodes.forEach((category) => {
    const slug = createSlugFromTitle(category.titolo);

    if (slug) {
      const recipes = category.ricettario
        .filter((x) => Boolean(x))
        .sort((a, b) => Date.parse(b._createdAt) - Date.parse(a._createdAt));

      const numOfPages = Math.ceil((recipes.length - 1) / ITEM_PER_PAGE);

      Array.from({ length: numOfPages }).forEach((_, index) => {
        const currentPage = index + 1;
        const start = index * ITEM_PER_PAGE + 1;

        createPage({
          path: currentPage === 1 ? slug : `${slug}/${currentPage}/`,
          component: resolve("./src/templates/Category.tsx"),
          context: {
            titolo: category.titolo,
            category_id: category._id,
            lastItemId: recipes[0]._id,
            numOfPages,
            currentPage,
            start,
            ITEM_PER_PAGE,
            articles: recipes.map((item) => item._id),
          },
        });
      });
    }
  });

In ordine abbiamo

  1. Estratto {createPages} dal parametro actions che ci espone la funzione
  2. Utilizzato la funzione async graphql per andare a recuperare i dati della nostra query e assegnati alla variabile allCategories
  3. Iterato la nostra variabile con un forEach loop
  4. In cui andiamo per ogni categoria a crearci un'array di ricette ordinato per data di creazione
  5. Usato il metodo Array.from() per creare un array di lunghezza pari a il numero di ricette / il numero di ricette che vogliamo per pagina.
  6. Utilizzato l'utils createPage per creare una nuova pagina.

Queest'ultima accetta:

  • path: percorso a cui vogliamo creare la pagina
  • component: il template che vogliamo usare in questa pagina (create il file in src/template)
  • context: contiene valori a cui vogliamo accedere sul frontend

A questo punto lanciamo

npm run clean & npm run develop
e andando su una route che non esiste dovremmo trovare questo

Lista di categorie paginate

Creare una pagina sul frontend con Gatsby

Ora last but not least dobbiamo andare a lavorare sul frontend per creare la nostra pagina. Quindi nel nostro file Category.tsx andiamo a:


import { graphql, HeadFC, PageProps } from "gatsby"

//...body e style del component

export const query = graphql`
  query CategoryPage(
    $lastItemId: String!
    $category_id: String!
    $ITEM_PER_PAGE: Int!
    $start: Int!
    $articles: [String]
  ) {
    allSanityRecipe(
      sort: { order: DESC, fields: _createdAt }
      skip: $start
      filter: { _id: { in: $articles } }
      limit: $ITEM_PER_PAGE
    ) {
      nodes {
        titolo
        riassunto
        ingredienti
        image {
          asset {
            gatsbyImageData
          }
        }
        cokkedby {
          complete_name
        }
      }
    }
    sanityRecipe(_id: { eq: $lastItemId }) {
      titolo
      riassunto
      image {
        asset {
          gatsbyImageData
        }
      }
    }
  }
`

Ora famose du chiacchiere su questa query diabolica.

  1. Il nome che assegniamo alla query dopo la keyword query deve essere unico e permetterà a gatsby di crearvi automaticamente i types per questa vostra query.
  2. Notiamo che dopo il nome si apre una parentesi in cui troviamo delle variabili ( e sono i valori che ci siamo passati nel context dal server 😏 )
  3. Cerchiamo tra tutte le nostre ricette allSanityRecipe le ricette che saranno il cui _id sarà nel nostro array $articles, ordinate dalla più recente
  4. Usiamo i parametri di limit per dire quanti elemente deve ritornarci e start da quale elemento deve iniziare a contere
  5. E ci prendiamo tutti valori di cui abbiamo bisogno.
  6. Abbiamo una seconda source di dati composta da sanityRecipe che va a ritornarci una singola ricetta che ci servirà a mostrare l'ultimo elemento creato.

A Questo punto nel nostro component

const Category: React.FC<
  PageProps<Queries.CategoryPageQuery, ContextProps>
> = ({ data, pageContext }) => {
//... corpo del componente
}

Andiamo a tipizzarlo e in data troveremo tutti i dati estratti dalla nostra query mentre in pageContext abbiamo i valori che ci siamo passati durante la creazione della pagina lato server.

A questo punto abbiamo tutto eeeeeeee.... TA DAAAN!

Pagina finale delle categorie

Prossimo Progetto

Come creare un blog statico usando Gatsbyjs

Come creare un blog statico usando Gatsbyjs

Un blog di cucina statico con gestionale.

gatsby

Informazioni aggiuntive

Livello: Intermedio

113 lezioni

12 ore di videocorso

1 Progetti pratici

27 studenti iscritti

Voto Medio:

4

Prezzo originale: 19.99€

Supporto Premium

text

Scopri il corso completo

Corso di Gatsby.js: Teoria, Prog...


27

4

Copertina
Corso di Gatsby.js: Teoria,...