1658128999
Building a custom blog doesn’t have to be hard, and you don’t have to do all of the hard work from scratch!
Gatsby, a static site generator for React, is an amazing tool that comes pre-configured with GraphQL and it allows you to easily get up and running.
Since Gatsby is a static site generator for React, you should have some React knowledge prior to taking this tutorial.
You should also be familiar with how to use the command line / terminal as we’ll be installing some packages with npm.
See more at: https://ultimatecourses.com/blog/building-a-blog-with-gatsby-and-graphql
1658128999
Building a custom blog doesn’t have to be hard, and you don’t have to do all of the hard work from scratch!
Gatsby, a static site generator for React, is an amazing tool that comes pre-configured with GraphQL and it allows you to easily get up and running.
Since Gatsby is a static site generator for React, you should have some React knowledge prior to taking this tutorial.
You should also be familiar with how to use the command line / terminal as we’ll be installing some packages with npm.
See more at: https://ultimatecourses.com/blog/building-a-blog-with-gatsby-and-graphql
1651813200
Why use this package over the other available Elm GraphQL packages? This is the only one that generates type-safe code for your entire schema. Check out this blog post, Type-Safe & Composable GraphQL in Elm, to learn more about the motivation for this library. (It's also the only type-safe library with Elm 0.18 or 0.19 support, see this discourse thread).
I built this package because I wanted to have something that:
See an example in action on Ellie. See more end-to-end example code in the examples/
folder.
dillonkearns/elm-graphql
is an Elm package and accompanying command-line code generator that creates type-safe Elm code for your GraphQL endpoint. You don't write any decoders for your API with dillonkearns/elm-graphql
, instead you simply select which fields you would like, similar to a standard GraphQL query but in Elm. For example, this GraphQL query
query {
human(id: "1001") {
name
homePlanet
}
}
would look like this in dillonkearns/elm-graphql
(the code in this example that is prefixed with StarWars
is auto-generated)
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
import StarWars.Object
import StarWars.Object.Human as Human
import StarWars.Query as Query
import StarWars.Scalar exposing (Id(..))
query : SelectionSet (Maybe HumanData) RootQuery
query =
Query.human { id = Id "1001" } humanSelection
type alias HumanData =
{ name : String
, homePlanet : Maybe String
}
humanSelection : SelectionSet HumanData StarWars.Object.Human
humanSelection =
SelectionSet.map2 HumanData
Human.name
Human.homePlanet
GraphQL and Elm are a perfect match because GraphQL is used to enforce the types that your API takes as inputs and outputs, much like Elm's type system does within Elm. elm-graphql
simply bridges this gap by making your Elm code aware of your GraphQL server's schema. If you are new to GraphQL, graphql.org/learn/ is an excellent way to learn the basics.
After following the installation instructions to install the @dillonkearns/elm-graphql
NPM package and the proper Elm packages (see the Setup section for details). Once you've installed everything, running the elm-graphql
code generation tool is as simple as this:
npx elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src
If headers are required, such as a Bearer Token, the --header
flag can be supplied.
npx elm-graphql https://elm-graphql.herokuapp.com --base StarWars --output examples/src --header 'headerKey: header value'
There is a thorough tutorial in the SelectionSet
docs. SelectionSet
s are the core concept in this library, so I recommend reading through the whole page (it's not very long!).
The examples/
folder is another great place to start.
If you want to learn more GraphQL basics, this is a great tutorial, and a short read: graphql.org/learn/
My Elm Conf 2018 talk goes into the philosophy behind dillonkearns/elm-graphql
(Skip to 13:06 to go straight to the dillonkearns/elm-graphql
demo).
elm-graphql
using the Scalar Codecs feature. If you're wondering why code is generated a certain way, you're likely to find an answer in the Frequently Asked Questions (FAQ).
There's a very helpful group of people in the #graphql channel in the Elm Slack. Don't hesitate to ask any questions about getting started, best practices, or just general GraphQL in there!
dillonkearns/elm-graphql
generates Elm code that allows you to build up type-safe GraphQL requests. Here are the steps to setup dillonkearns/elm-graphql
.
Add the dillonkearns/elm-graphql
elm package as a dependency in your elm.json
. You will also need to make sure that elm/json
is a dependency of your project since the generated code has lots of JSON decoders in it.
elm install dillonkearns/elm-graphql
elm install elm/json
Install the @dillonkearns/elm-graphql
command line tool through npm. This is what you will use to generate Elm code for your API. It is recommended that you save the @dillonkearns/elm-graphql
command line tool as a dev dependency so that everyone on your project is using the same version.
npm install --save-dev @dillonkearns/elm-graphql
# you can now run it locally using `npx elm-graphql`,
# or by calling it through an npm script as in this project's package.json
Run the @dillonkearns/elm-graphql
command line tool installed above to generate your code. If you used the --save-dev
method above, you can simply create a script in your package.json like the following:
{
"name": "star-wars-elm-graphql-project",
"version": "1.0.0",
"scripts": {
"api": "elm-graphql https://elm-graphql.herokuapp.com/api --base StarWars"
}
With the above in your package.json
, running npm run api
will generate dillonkearns/elm-graphql
code for you to call in ./src/StarWars/
. You can now use the generated code as in this Ellie example or in the examples
folder.
You can do real-time APIs using GraphQL Subscriptions and dillonkearns/elm-graphql
. Just wire in the framework-specific JavaScript code for opening the WebSocket connection through a port. Here's a live demo and its source code. The demo server is running Elixir/Absinthe.
Thank you Mario Martinez (martimatix) for all your feedback, the elm-format PR, and for the incredible logo design!
Thank you Mike Stock (mikeastock) for setting up Travis CI!
Thanks for the reserved words pull request @madsflensted!
A huge thanks to @xtian for doing the vast majority of the 0.19 upgrade work! :tada:
Thank you Josh Adams (@knewter) for the code example for Subscriptions with Elixir/Absinthe wired up through Elm ports!
Thank you Romario for adding OptionalArgument.map
!
Thank you Aaron White for your pull request to improve the performance and stability of the elm-format
step! 🎉
All core features are supported. That is, you can build any query or mutation with your dillonkearns/elm-graphql
-generated code, and it is guaranteed to be valid according to your server's schema.
dillonkearns/elm-graphql
will generate code for you to generate subscriptions and decode the responses, but it doesn't deal with the low-level details for how to send them over web sockets. To do that, you will need to use custom code or a package that knows how to communicate over websockets (or whichever protocol) to setup a subscription with your particular framework. See this discussion for why those details are not handled by this library directly.
I would love to hear feedback if you are using GraphQL Subscriptions. In particular, I'd love to see live code examples to drive any improvements to the Subscriptions design. Please ping me on Slack, drop a message in the #graphql channel, or open up a Github issue to discuss!
I would like to investigate generating helpers to make pagination simpler for Connections (based on the Relay Cursor Connections Specification). If you have ideas on this chime in on this thread.
See the full roadmap on Trello.
Author: dillonkearns
Source Code: https://github.com/dillonkearns/elm-graphql
License: View license
1603587600
Nowadays, creating a blog is easy. But, with all the different options available, you might go crazy by just doing the research.
Should you choose WordPress and tweak the theme to get it the way you like, or a static site generator with no admin interface and complicated build processes?
All you want is a simple blog where you can write about the shit you love.
So why can’t it be simpler? Well, now it is with the DevDojo Dev Blog!
Your Dev Blog will have a default subdomain username.devdojo.com
, and you may choose to add a custom domain as well.
If you wish to use a custom domain, add a CNAME record to your Cloudflare DNS, with your subdomain in the CONTENT section. Wait a few minutes and you’ll have your custom domain resolving in minutes.
Want a video on how to do this, You got it!
At the moment of writing this, there are 2 themes you can choose from (many more to come). Each theme will have a light/dark mode and is built for speed!
Themes are built using the awesome TailwindCSS library. If you pair that with PurgeCSS, minimal javascript, and Cloudflare caching. That’s just a recipe for a fast website.
#developer-blog #dev-blog #web-development #portfolio #blog #blogging #developer-tools #writing
1613361840
In this video you can create a blog using Gatsby alongside markdown files and GraphQL.
If you did enjoy the video makes sure to drop it a like, comment and subscribe for more JAMStack.
#gatsby #graphql #api #web-development
1658143800
Criar um blog personalizado não precisa ser difícil e você não precisa fazer todo o trabalho duro do zero!
Gatsby, um gerador de site estático para React, é uma ferramenta incrível que vem pré-configurada com GraphQL e permite que você comece a usar facilmente.
Como o Gatsby é um gerador de site estático para o React, você deve ter algum conhecimento do React antes de fazer este tutorial.
Você também deve estar familiarizado com o uso da linha de comando/terminal, pois instalaremos alguns pacotes com o npm.
Precisamos instalar o Gatsby CLI (interface de linha de comando) para construir novos projetos Gatsby.
Para instalar a ferramenta Gatsby CLI, execute o seguinte npm
comando:
npm install -g gatsby-cli
Gatsby tem uma série de arquivos iniciais chamados Gatsby Starters que permitem que você gire rapidamente diferentes tipos de sites Gatsby.
Gatsby fornece um blog inicial que você pode usar para começar a funcionar rapidamente.
Se você não estiver familiarizado com Gatsby ou GraphQL, recomendo seguir o tutorial detalhado para aprender os detalhes.
Para criar um blog com o iniciador de blog, basta executar:
gatsby new <<my-blog-name>> https://github.com/gatsbyjs/gatsby-starter-blog
Em seguida, adicione seus arquivos de blog markdown e personalize o conteúdo do seu coração.
Vamos percorrer as etapas de criação de um blog Gatsby do zero usando o iniciador padrão.
Primeiro, crie seu projeto inicial executando:
gatsby new <<my-blog-name>> && cd <<my-blog-name>>
gatsby develop
Ao abrir localhost:8000
em seu navegador, você verá o aplicativo padrão Gatsby.
Vamos em frente e remover todo o clichê. Deixaremos a estrutura de arquivos atual dentro do src/
diretório, mas removeremos todos os arquivos de dentro.
rm -rf src/**/*.*
Como o Gatsby é um gerador de site estático para o React, você pode escrever componentes simples do React, como faria com o create react app.
Aqui está a arquitetura atual do nosso aplicativo:
components/
: Contém todos os seus componentes React (ou seja, navegação).pages/
: Contém todas as páginas com rotas exclusivas: qualquer arquivo JavaScript localizado neste diretório será acessível através de sua própria URLmy-website/<<page-name>>
images/
: Contém todos os recursos de imagem para nosso projeto.Vamos em frente e adicionar alguns dos arquivos que precisaremos para construir nosso blog.
Nosso blog terá quatro páginas:
Vamos criar um arquivo JavaScript para cada uma dessas páginas dentro do pages
diretório:
index.js
about.js
blog.js
contact.js
Como também removemos todas as imagens do nosso projeto, precisamos remover a referência gatsby-icon
para corrigir nosso servidor de desenvolvimento.
Dentro gatsby-config.js
de , remova o ícone do options
objeto.
// delete me
icon: `src/images/gatsby-icon.png`
Para verificar se tudo está funcionando conforme o esperado, vamos ter index.js
no pages/
diretório retornar algum JSX simples.
// pages/index.js
import React from "react";
const Home = () => (
<div>
<h1>Home</h1>
</div>
);
export default Home;
Quando reiniciamos nosso servidor de desenvolvimento e vamos para nosso navegador, devemos ver isso:
Vamos adicionar JSX semelhante aos outros três componentes de página:
// pages/about.js
import React from "react";
const About = () => (
<div>
<h1>About</h1>
</div>
);
export default About;
// pages/blog.js
import React from "react";
const Blog = () => (
<div>
<h1>Blog</h1>
</div>
);
export default Blog;
// pages/contact.js
import React from "react";
const Contact = () => (
<div>
<h1>Contact</h1>
</div>
);
export default Contact;
Se voltarmos ao navegador e adicionarmos um /about
ao final do nosso localhost
URL, devemos ver a página sobre. Da mesma forma, isso funcionará para /blog
e /contact
.
Todas as nossas páginas estão renderizando, mas não seria legal se tivéssemos um componente de navegação que pudéssemos usar para alternar entre visualizações de página? Vamos construir um!
Primeiro vamos criar dois novos arquivos no components/
diretório: Nav.js
e nav.css
.
Dentro Nav.js
adicione o seguinte código:
// Nav.js
import React from "react";
const Nav = () => (
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/about">About</a>
</li>
<li>
<a href="/blog">Blog</a>
</li>
<li>
<a href="/contact">Contact</a>
</li>
</ul>
</nav>
);
export default Nav;
Como queremos a barra de navegação em cada página, podemos importá-la para cada página individual e renderizá-la, mas há uma maneira mais fácil.
Podemos usar um <Layout>
componente para garantir que nossa navegação seja renderizada em cada página, sem precisar importar e renderizar manualmente para cada uma.
É assim que nosso <Layout>
componente ficará:
A barra de navegação ficará no topo da página e todo o conteúdo da página será renderizado em um <main>
elemento abaixo.
Dentro de components/
criar Layout.js
.
Primeiro, vamos importar React, Prop Types e nosso componente Nav:
// Layout.js
import React from "react";
import PropTypes from "prop-types";
import Nav from "./Nav";
Em seguida, criaremos um componente React funcional sem estado, passando children
como um prop.
// Layout.js
const Layout = ({ children }) => (
<>
<Nav />
<main>{ children }</main>
</>
);
export default Layout;
Também queremos garantir que estamos passando JSX para o <Layout>
componente, então usaremos PropTypes para impor isso.
// Layout.js
import React from "react";
import PropTypes from "prop-types";
import Nav from "./Nav";
const Layout = ({ children }) => (
<>
<Nav />
<main>{ children }</main>
</>
);
Layout.propTypes = {
children: PropTypes.node.isRequired
};
export default Layout;
Vamos ver se nosso <Layout>
componente funciona.
De volta ao index.js
, vamos importar nosso <Layout>
componente e renderizá-lo em torno do conteúdo da nossa página.
// index.js
import React from "react";
import Layout from "../components/Layout";
const Home = () => (
<Layout>
<h1>Home</h1>
</Layout>
);
export default Home;
Se formos ao nosso navegador, devemos ver a navegação aparecendo acima do título da nossa página:
Vamos adicionar o <Layout>
componente às outras três páginas.
// pages/about.js
import React from "react";
import Layout from "../components/Layout";
const About = () => (
<Layout>
<h1>About</h1>
</Layout>
);
export default About;
// pages/blog.js
import React from "react";
import Layout from "../components/Layout";
const Blog = () => (
<Layout>
<h1>Blog</h1>
</Layout>
);
export default Blog;
// pages/contact.js
import React from "react";
import Layout from "../components/Layout";
const Contact = () => (
<Layout>
<h1>Contact</h1>
</Layout>
);
export default Contact;
Se voltarmos ao navegador, agora podemos clicar em cada item de navegação e ver o conteúdo da respectiva página.
E enquanto isso funciona, você notará uma nova renderização em cada página. Isso ocorre porque estamos usando a <a>
tag para vincular as páginas e isso força uma nova renderização.
Como solução, o Gatsby fornece um <Link>
componente para lidar com o roteamento de páginas.
Vamos voltar Nav.js
e corrigir o roteamento da página.
Primeiro vamos importar o Link.
// Nav.js
import React from "react";
import { Link } from "gatsby";
Em seguida, vamos substituir todas as <a>
tags <Link>
e alterar os href=
atributos para to=
atributos.
// Nav.js
import React from "react";
import { Link } from "gatsby";
const Nav = () => (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/blog">Blog</Link>
</li>
<li>
<Link to="/contact">Contact<Link>
</li>
</ul>
</nav>
);
export default Nav;
Voltando ao navegador, o roteamento da página deve ser instantâneo quando clicamos em um item de navegação.
Agora que nosso aplicativo funciona, vamos adicionar um pouco de estilo para torná-lo mais bonito.
O Gatsby simplifica a adição de estilos específicos quando um link de navegação está ativo.
Há duas maneiras de adicionar estilos a um link ativo:
activeStyle
: usa CSS-in-JS embutido para estilizar um elemento quando ativo.<Link activeStyle={{ backgroundColor: 'red' }}>My link</Link>
activeClassName
: dá ao elemento link um nome de classe quando ativo.<Link activeClassName="active-link">My link</Link>
Eu geralmente uso activeClassName
se tiver vários links, porém usaremos activeStyle
aqui para demonstrar CSS-in-JS.
Também adicionei alguns className
atributos ao código JSX que usaremos para estilizar o restante de nossa navegação.
// Nav.js
import React from "react";
import { Link } from "gatsby";
import "./nav.css";
const Nav = () => (
<nav className="nav">
<ul className="nav-list">
<li className="nav-list-item">
<Link
activeStyle={{ borderBottom: "2px solid #a64ac9" }}
to="/">
Home
</Link>
</li>
<li className="nav-list-item">
<Link
activeStyle={{ borderBottom: "2px solid #a64ac9" }}
to="/about">
About
</Link>
</li>
<li className="nav-list-item">
<Link
activeStyle={{ borderBottom: "2px solid #a64ac9" }}
to="/blog">
Blog
</Link>
</li>
<li className="nav-list-item">
<Link
activeStyle={{ borderBottom: "2px solid #a64ac9" }}
to="/contact">
Contact
</Link>
</li>
</ul>
</nav>
);
export default Nav;
Agora, cada link, quando selecionado, terá um sublinhado de 2px
.
Dentro do nav.css
arquivo no components/
diretório e adicione o seguinte código.
/* nav.css */
.nav {
padding: 24px;
}
.nav-list {
list-style: none;
display: flex;
margin: 0;
padding: 0;
}
.nav-list-item {
margin-right: 24px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
font-size: 1.5em;
}
.nav-list a {
color: #a64ac9;
text-decoration: none;
border-bottom: 2px transparent;
transition: border 0.1s linear;
}
.nav-list a:hover,
.nav-list a:focus {
border-bottom: 2px solid #a64ac9;
}
Não esqueça de importar nav.css
em Nav.js
:
// Nav.js
...
import "./nav.css";
...
Agora vamos adicionar algum estilo ao Layout.js
. Crie layout.css
no components/
diretório.
/* layout.css */
html,
body {
padding: 0;
margin: 0;
overflow-x: hidden;
}
.main {
padding: 24px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
background-color: #a64ac9;
height: 100%;
color: #ffffff;
}
.main h1 {
font-size: 5em;
}
.main p {
font-size: 2em;
}
Importe o arquivo CSS Layout.js
e adicione um nome de classe de layout
ao elemento externo <div>
e um nome de classe de main
ao <main>
elemento.
// Layout.js
...
import "./layout.css";
...
<div className="layout">
<Nav />
<main className="main">{ children }</main>
</div>
...
Por último, vou adicionar algum conteúdo de preenchimento a index.js
, about.js
e contact.js
. Eu adicionei 5 parágrafos com texto lorem ipsum a cada uma das três páginas.
// index.js, about.js, contact.js
...
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ea dignissimos
aut consequuntur aspernatur corrupti ratione, odit similique tenetur
accusantium, est nostrum esse minus iure voluptatum nihil cumque
blanditiis non? Odit.
</p>
...
Seu site agora deve ficar muito melhor!
Agora é hora de adicionar alguns blogs!
Dentro do pages/
diretório, crie três pastas: 2020-01-01-my-first-blog
, 2020-02-14-valentines-day
, 2020-04-01-april-fools
.
Dentro de cada uma dessas pastas, adicione um index.md
arquivo com a seguinte estrutura:
---
path: '/my-first-blog'
date: '2020-01-01'
title: 'My First Blog'
author: 'Emma Bostian'
description: 'This is my very first blog of 2020!'
---
Here is my main content
It is very interesting.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ea dignissimos
aut consequuntur aspernatur corrupti ratione, odit similique tenetur
accusantium, est nostrum esse minus iure voluptatum nihil cumque
blanditiis non? Odit.
Tudo entre os três hífens é chamado de frontmatter. Frontmatter é essencialmente metadados para sua postagem no blog.
Para cada postagem do blog, adicione algum frontmatter, contendo os seguintes dados:
path
: o caminho do URL para seu blogdate
: A data de publicaçãotitle
: O título da postagem do blogauthor
: O autor da postagem do blogdescription
: A descrição da postagem do blogTudo após os hífens de fechamento é o corpo principal da postagem do blog. Você pode adicionar o que quiser aqui.
Adicione conteúdo de remarcação para cada uma das nossas três postagens do blog.
Agora que temos arquivos markdown, queremos renderizá-los em nossa blog.js
página.
Primeiro precisamos instalar as dependências:
No seu terminal, execute o seguinte comando:
yarn add gatsby-transformer-remark
Em seguida, em gatsby-config.js
, adicione gatsby-transformer-remark
à lista de plugins.
// gatsby-config.js
plugins: [
...
`gatsby-transformer-remark`,
...
]
Também precisamos adicionar outro plugin para gatsby-source-filesystem
informar ao GraphQL onde encontrar nossas postagens de blog: nosso pages/
diretório.
// gatsby-config.js
{
plugins: [
...
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages`,
},
}
...
]
}
Reinicie seu servidor de desenvolvimento e vá para http://localhost:8000/___graphql
.
Gatsby vem pré-configurado com GraphQL, o que significa que temos acesso ao GraphiQL.
Para obter uma lista de todas as postagens do blog, usaremos o AllMarkdownRemark
plugin. Selecione as seguintes opções no painel Explorer:
AllMarkdownRemark > edges > node > frontmatter > date title
Em seguida, pressione o botão de reprodução.
Você deve ver os dados da postagem do seu blog no painel direito.
Copie esta consulta GraphQL e vá para blog.js
.
Primeiro, importe graphql
de gatsby
.
// blog.js
...
import { graphql } from "gatsby";
...
Em seguida, após a exportação do blog, adicione o seguinte código, colando na consulta do GraphQL que acabamos de copiar do GraphiQL, onde diz<<Your code here>>
export const AllBlogsQuery = graphql`
<<your code here>>
`
Minha consulta se parece com isso (adicionei description
path
, e author
à lista de dados a serem recuperados do frontmatter).
// blog.js
export const AllBlogsQuery = graphql`
query AllBlogPosts {
allMarkdownRemark {
edges {
node {
frontmatter {
date
title
description
author
path
}
}
}
}
}
`
A última coisa que precisamos fazer é passar data
da consulta como parâmetro para a página do blog. Vamos registrá-lo no console para ver se está funcionando.
// blog.js
...
const Blog = ({ data }) => (
<Layout>
<h1>Blog</h1>
{ console.log(data) }
</Layout>
);
...
Agora vamos iterar sobre os dados do nosso blog e criar nós para cada um deles.
Crie dois novos arquivos na pasta do componente chamada Post.js
e post.css
.
Post
terá cinco argumentos:
title
author
description
date
path
// Post.js
import React from "react";
import { Link } from "gatsby";
import "./post.css";
const Post = ({ title, author, date, description, path }) => (
<div className="post">
<h3 className="post-title">{ title }</h3>
<p className="post-description">{ description }</p>
<p className="post-written-by">
Written by { author } on { date }
</p>
<Link to={ path }>Read more</Link>
</div>
);
export default Post;
Aqui está o estilo para as nossas postagens do blog:
/* post.css */
.post {
margin-bottom: 80px;
padding-bottom: 80px;
border-bottom: 2px solid white;
}
.post .post-title {
font-size: 3em;
margin: 0;
}
.post .post-description {
font-size: 1.5em;
}
.post .post-written-by {
font-size: 1em;
}
.post a {
background-color: white;
color: #a64ac9;
padding: 16px 24px;
text-decoration: none;
margin-top: 16px;
display: inline-block;
}
Agora podemos importar Post
e blog.js
renderizar uma nova postagem para cada arquivo de remarcação:
// blog.js
...
import Post from "../components/Post";
...
const Blog = ({ data }) => (
<Layout>
<h1>Blog</h1>
{
data.allMarkdownRemark.edges.map(post => {
const { title, author, date, description, path } = post.node.frontmatter;
return (
<Post
title={title}
author={author}
date={date}
description={description}
key={`${date}__${title}`}
path={path}
/>
)
})
}
</Layout>
);
Seu blog agora deve ficar assim:
Agora que geramos uma lista de blogs em nossa página de blog, como podemos criar uma página para cada blog que aparece quando o usuário clica em 'Leia mais'?
Poderíamos criar manualmente uma página para cada postagem, mas isso seria tedioso.
Felizmente Gatsby, em combinação com node.js, fornece funcionalidade para gerar páginas dinamicamente.
Vamos primeiro criar a consulta GraphQL para recuperar dados de uma postagem de blog individual.
Quando criamos o esquema GraphQL para recuperar todas as postagens do blog, usamos o allMarkdownRemark
plugin.
Desta vez, queremos apenas os dados de uma postagem de blog individual, então usaremos o markdownRemark
plug-in.
No painel do Explorer à esquerda, selecione:
`markdownRemark > frontmatter(purple) > path > eq: "_"
Certifique-se de selecionar o roxo frontmatter
para esta parte da consulta; é um argumento versus um nome de campo.
Isso informa ao GraphQL que selecionaremos um ativo específico pelo caminho, que será passado como parâmetro.
Para esta postagem individual, queremos obter vários dados do frontmatter, então selecionaremos
markdownRemark > html, frontmatter (blue) > author date path title
Certifique-se de selecionar o azul frontmatter
para esta parte da consulta; é um nome de campo versus um argumento.
Em seguida, onde estamos passando um argumento para markdownRemark
, temos que dar ao GraphQL um eq
valor para procurar. No nosso caso, passaremos o path
para a postagem do blog cujo conteúdo queremos exibir.
Primeiro precisamos passar esse argumento para nossa consulta, antes de podermos passá-lo para o markdownRemark
plugin. Você também pode alterar o nome da consulta para ser mais semântico:
query BlogPost($path: String!) {
markdownRemark(frontmatter: { path: eq: $path }}) {
frontmatter {
author
date
title
path
}
html
}
}
String!
informa ao GraphQL que o argumento de caminho que estamos passando é do tipo String
e é obrigatório.
Agora vamos testar se essa consulta realmente funciona.
Se pressionarmos play, obtemos um erro:
Isso se deve ao fato de que nossa consulta espera um argumento, mas não passamos um!
Abra o painel na parte inferior chamado Query Variables e digite o seguinte:
{
"path": "/april-fools"
}
Quando pressionamos o botão play agora, obtemos os dados de volta para o nosso blog do Dia da Mentira.
Agora que temos nossa consulta, o que fazemos com ela?
Primeiro, vamos construir um modelo que denotará como cada postagem do blog deve ser estruturada.
No src/
diretório, crie uma nova pasta chamada templates
e adicione um arquivo dentro dela chamado blogTemplate.js
.
Primeiro precisamos incluir algumas importações:
// templates/blogTemplate.js
import React from "react";
import { graphql, Link } from "gatsby";
import Layout from "../components/Layout";
Em seguida, vamos criar o esqueleto da função:
// templates/blogTemplate.js
...
export default function Template({ data }) {
return ()
};
Este modelo receberá os dados do nosso blog e os renderizará de acordo.
Por fim, vamos adicionar nossa consulta GraphQL na parte inferior do arquivo.
// templates/blogTemplate.js
...
export const postQuery = graphql`
query BlogPost($path: String!) {
markdownRemark(frontmatter: { path: { eq: $path }}) {
frontmatter {
author
date
title
path
}
html
}
}
`;
Agora vamos construir nossa estrutura de postagem de blog. Primeiro, vamos pegar o post
e o title
, author
e date
dos dados.
// templates/blogTemplate.js
...
export default function Template({ data }) {
const post = data.markdownRemark;
const { title, author, date } = post.frontmatter;
...
Vamos envolver nosso JSX no <Layout>
componente, e dentro teremos:
<div>
contendo o dangerouslySetInnerHTML
atributo, que recebe a post.html
marcação como valor.// templates/blogTemplate.js
...
export default function Template({ data }) {
const post = data.markdownRemark;
const { title, author, date } = post.frontmatter;
return (
<Layout>
<Link to="/">Back to blogs</Link>
<h1>{title}</h1>
<p>Posted by {author} on {date}</p>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</Layout>
)
};
...
Aqui está o blogTemplate.js
arquivo completo:
// templates/blogTemplate.js
import React from "react";
import { graphql, Link } from "gatsby";
import Layout from "../components/Layout";
export default function Template({ data }) {
const post = data.markdownRemark;
const { title, author, date } = post.frontmatter;
return (
<Layout>
<Link to="/">Back to blogs</Link>
<h1>{title}</h1>
<p>Posted by {author} on {date}</p>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</Layout>
)
};
export const postQuery = graphql`
query BlogPost($path: String!) {
markdownRemark(frontmatter: { path: { eq: $path }}) {
frontmatter {
author
date
title
path
}
html
}
}
`;
Agora que temos nosso modelo, vamos usá-lo! Temos que dizer ao Gatsby para gerar páginas dinamicamente para cada postagem do blog, então vamos para gatsby-node.js
.
Vamos primeiro exigir o path
módulo:
// gatsby-node.js
const path = require('path');
Vamos usar a exports.createPages
API para gerar dinamicamente nossas páginas.
// gatsby-node.js
...
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPages } = boundActionCreators;
const postTemplate = path.resolve('src/templates/blogTemplate.js');
}
Agora temos que retornar uma consulta para obter todas as postagens do blog, para que possamos iterar e gerar nossas páginas. Já temos essa consulta de uma etapa anterior, e tudo o que precisamos para cada postagem é o seu arquivo path
.
// gatsby-node.js
...
return graphql(`
{
allMarkdownRemark {
edges {
node {
frontmatter {
path
}
}
}
}
}
`)
Assim que recebermos uma resposta da consulta, queremos rejeitar a promessa se ocorrer um erro e, caso contrário, criar uma página para cada postagem.
Isso criará uma postagem no caminho designado recebido dos resultados da consulta e usará o postTemplate
que declaramos acima (nosso blogPost.js
modelo) para renderizar cada postagem.
// gatsby-node.js
...
return graphql(`
{
allMarkdownRemark {
edges {
node {
frontmatter {
path
}
}
}
}
}
`).then(res => {
if (res.errors) { return Promise.reject(res.errors) }
res.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate
})
})
Aqui está o gatsby-node.js
arquivo completo:
// gatsby-node.js
const path = require("path");
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators;
const postTemplate = path.resolve("src/templates/blogTemplate.js");
return graphql(`
{
allMarkdownRemark {
edges {
node {
frontmatter {
path
}
}
}
}
}
`).then(res => {
if (res.errors) {
return Promise.reject(res.errors)
}
res.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
})
})
})
};
Agora estamos prontos para ver se funcionou!
Reinicie seu servidor de desenvolvimento, vá até o navegador e clique em um dos links de postagem do blog “Leia mais”:
Vou adicionar um pouco mais de estilo para torná-lo mais bonito.
Vou criar um blogTemplate.css
arquivo no templates/
diretório:
/* blogTemplate.css */
.blogTemplate .blogTemplate-title {
margin: 80px 0 24px;
}
.blogTemplate .blogTemplate-posted-by {
font-size: 1.2em;
}
.blogTemplate a {
color: #fff;
}
Em seguida, importarei o arquivo CSS blogTemplate.js
e adicionarei os nomes de classe apropriados. Também envolverei o JSX dentro de <Layout>
um <div>
para que possamos dar a ele um nome de classe de blogTemplate
.
// templates/blogTemplate.js
import React from "react";
import { graphql, Link } from "gatsby";
import Layout from "../components/Layout";
import "./blogTemplate.css";
export default function Template({ data }) {
const post = data.markdownRemark;
const { title, author, date } = post.frontmatter;
return (
<Layout>
<div className='blogTemplate'>
<Link to="/blogs">Back to blogs</Link>
<h1 className="blogTemplate-title">{ title }</h1>
<p className='blogTemplate-posted-by'>Posted by { author } on { date }</p>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
</Layout>
)
};
export const postQuery = graphql`
query BlogPost($path: String!) {
markdownRemark(frontmatter: { path: { eq: $path }}) {
frontmatter {
author
date
title
path
}
html
}
}
`;
Sua postagem no blog deve ficar assim:
Agora que temos um blog funcionando, vamos implantá-lo no Netlify!
Primeiro, precisamos estabelecer nosso blog como um repositório Git.
No GitHub, crie um novo repositório:
Com o terminal, no diretório do projeto execute os seguintes comandos:
git init
git add .
git commit -m "Adding my blog files"
git remote add origin <<repo-link>>
git push -u origin master
Assim que seu código estiver no GitHub, é hora de implantar!
Crie uma conta no Netlify ou entre.
Clique em “Novo site do Git” e autentique com o GitHub.
Selecione seu repositório recém-criado e clique em “Implantar”.
Toda vez que você enviar para o branch master, seu site será implantado automaticamente (você pode alterar a configuração de implantação, mas esse é o padrão).
Você pode até adicionar um domínio personalizado para realmente tornar o blog seu.
E é isso! Espero que isso tenha sido útil para explicar o processo de construção de um blog com Gatsby.
Esse processo é tedioso, então, uma vez que você entenda a arquitetura, eu recomendaria usar o iniciador de blog Gatsby.
Feliz blogar!
Fonte: https://ultimatecourses.com/blog/building-a-blog-with-gatsby-and-graphql