Construye y Publica Tu Blog Personal con Gatsby y Netlify, parte 2

|\|370
10 min readJan 17, 2018

--

¡ATENCIÓN! Lo que vas a leer a seguir NO es totalmente compatible con la nueva versión de Gatsby 2.0. Déjame un mensaje abajo en los comentarios si quieres que yo publique una nueva serie de artículos actualizada.

Arranquemos con la segunda parte de esta serie de artículos adónde construiremos y publicaremos un nuevo blog utilizando Gatsby y Netlify. Si aún no la leíste, recomiendo que empieces leyendo ahora mismo la primera parte a través de 👉 este enlace.

Sitio estático, contenido dinámico

Hasta acá habíamos llegado.

¡Tu página ya luce increíble! Tus usuarios pueden navegar por el sitio y cualquier nueva modificación que tu quieras hacer se hace sencilla con el código desacoplado. Agreguemos entonces al layout principal un pie de página así sentís un poco esa flexibilidad.

Abra el archivo src/layouts/index.js y hágale cambios para que se vea así:

import React from "react";
import Link from "gatsby-link";
const styles = {
listItem: {
display: 'inline-block',
marginRight: '1rem'
},
wrapper: {
margin: '0 auto',
maxWidth: 650,
border: '1px solid black'
},
header: {
padding: '5px',
marginBottom: '1.5rem'
},
siteTitleLink: {
textShadow: 'none',
backgroundImage: 'none'
},
siteTitle: {
display: 'inline'
},
list: {
listStyle: 'none',
float: 'right'
},
main: {
padding: '5px'
},
footer: {
background: 'black',
color: 'white',
padding: '5px'
}
};
const ListLink = props => (
<li style={styles.listItem}>
<Link to={props.to}>{props.children}</Link>
</li>
);
export default ({ children }) => (
<div style={styles.wrapper}>
<header style={styles.header}>
<Link to="/" style={styles.siteTitleLink}>
<h3 style={styles.siteTitle}>Mi blog</h3>
</Link>
<ul style={styles.list}>
<ListLink to="/">Início</ListLink>
<ListLink to="/sobre/">Sobre</ListLink>
<ListLink to="/contacto/">Contacto</ListLink>
</ul>
</header>
<main style={styles.main}>{children()}</main>
<footer style={styles.footer}>
<small>Mi blog</small>
</footer>
</div>
);

Si aún no lo tienes corriendo, levanta tu servidor de desarrollo y anda a tu navegador para ver lo que hicimos:

gatsby develop

Fíjate como el sitio ahora muestra un hermoso pie de página con el nombre del blog. Observa también que el texto “Mi blog” ahora está duplicado, apareciendo arriba en el header y abajo en el footer. Adelante simplificaremos aún más este código.

GraphQL

Gatsby incorpora al conjunto de convenciones que propone una tecnología llamada GraphQL. Su función es criar una interfaz flexible entre los datos que queremos mostrar en pantalla y la forma como los mostramos. Para comenzar a ver un poco de todo eso, empecemos por agregar un archivo de configuración con algún meta dato para mostrar. El título, por ejemplo.

Anda y agrega un archivo JavaScript llamado /gatsby-config.js en el directorio raíz de tu proyecto, la carpeta blog. Póngale lo siguiente y guárdalo:

module.exports = {
siteMetadata: {
title: 'Wow blog!'
}
};

Edita también el archivo src/layouts/index.js. Allí vamos a cambiar tres cosas importantes. Primero nuestro componente pasará a recibir un objeto con una nueva propiedad data definida. Luego cambiaremos el texto “Mi blog” presente en el header y en el footer por una expresión JavaScript que invoque los valores almacenados en data. Por fin agregaremos al archivo un bloque especial de texto describiendo una consulta GraphQL.

import React from "react";
import Link from "gatsby-link";
const styles = {
listItem: {
display: 'inline-block',
marginRight: '1rem'
},
wrapper: {
margin: '0 auto',
maxWidth: 650,
border: '1px solid black'
},
header: {
padding: '5px',
marginBottom: '1.5rem'
},
siteTitleLink: {
textShadow: 'none',
backgroundImage: 'none'
},
siteTitle: {
display: 'inline'
},
list: {
listStyle: 'none',
float: 'right'
},
main: {
padding: '5px'
},
footer: {
background: 'black',
color: 'white',
padding: '5px'
}
};
const ListLink = props => (
<li style={styles.listItem}>
<Link to={props.to}>{props.children}</Link>
</li>
);
export default ({ children, data }) => (
<div style={styles.wrapper}>
<header style={styles.header}>
<Link to="/" style={styles.siteTitleLink}>
<h3 style={styles.siteTitle}>{data.site.siteMetadata.title}</h3>
</Link>
<ul style={styles.list}>
<ListLink to="/">Início</ListLink>
<ListLink to="/sobre/">Sobre</ListLink>
<ListLink to="/contacto/">Contacto</ListLink>
</ul>
</header>
<main style={styles.main}>{children()}</main>
<footer style={styles.footer}>
<small>{data.site.siteMetadata.title}</small>
</footer>
</div>
);
export const query = graphql`
query LayoutQuery {
site {
siteMetadata {
title
}
}
}
`

Gatsby al procesar los fuentes extrae de ellos todas las consultas GraphQL, las procesa a parte y luego hace su resultado disponible para los componentes. Por esta razón es que no hay errores respecto a la variable global graphql que recién utilizamos sin propiamente importarla al archivo.

Reinicia el servidor de desarrollo con el comando que vimos anteriormente y deberías finalmente ver el texto “Wow blog!” tanto en el header como en el footer del sitio. Prueba editando el valor de la propiedad title en el archivo /gatsby-config.js y de esta vez bastará con que guarde los cambios hechos en el archivo para que estos se vean reflejados en la pantalla 😎.

Utilizando plug-ins

Gatsby está construido en base a una arquitectura modular, y tal cuál otros generadores de sitios estáticos permite que sus funcionalidades sean extendidas a través de plug-ins. En este enlace podes ver un listado de los más utilizados por la comunidad y para seguir construyendo tu blog tendrás que utilizar por lo menos dos de ellos.

Empieza corriendo el siguiente comando desde el directorio raíz de tu proyecto:

npm install gatsby-source-filesystem

Ahora agrega una nueva carpeta llamada /posts en el directorio raíz del proyecto y hágale cambios al archivo de configuración para que se vea como el ejemplo abajo. Reinicia el servidor para que tomen efecto los cambios.

module.exports = {
siteMetadata: {
title: 'Wow blog!'
},
plugins: [
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'posts',
path: `${__dirname}/posts/`
}
}
]
};

GraphiQL

Por defecto Gatsby integra una herramienta que sirve para explorar distintas fuentes de datos las que implementen una interfaz GraphQL. La puedes utilizar navegando hasta la dirección https://localhost:8000/__graphql. Abre la instancia GraphiQL de tu proyecto en un navegador para que empecemos a explorar la interfaz que gatsby-source-filesystem implementa.

En tu pantalla el panel inferior izquierdo puede aparecer colapsado.

El panel superior izquierdo de la interfaz de GraphiQL, tu deberás utilizar para escribir tus consultas y al ejecutarlas deberás ver luego a la derecha el resultado que retornan. Las combinaciones de teclas ctrl+spacebar y ctrl+enter, cuando presionadas sobre el panel superior izquierdo sirven respectivamente para activar la función de auto-completar y la de ejecutar una consulta.

Prueba ejecutando lo siguiente:

{
allFile {
totalCount
}
}

El resultado debería ser:

{
"data": {
"allFile": null
}
}

Eso sucede, ya debes haberte dado cuenta, porque no tenemos ningún archivo en nuestra carpeta /posts/.

¡Markdown FTW!

Nuestro blog no tendrá una base de datos como un blog Wordpress que guarda toda la información dinámica que tiene en una base de datos. El sistema de archivos del servidor que compila nuestro código fuente es la base de datos del blog y nuestros datos no están almacenados en tablas y columnas si no, en simples archivos de texto.

Creado por John Gruber en colaboración con Aaron Swartz, Markdown es un lenguaje de marcado ligero que hoy día se usa muchísimo para formatear archivos de texto utilizando ordenadores. Varios generadores de sitios estáticos soportan este formato y Gatsby no es excepción.

Cámbiate de modo desarrollador a modo redactor y agrega a tu carpeta /posts un nuevo archivo de texto con la extensión .md o .markdown. Siga el ejemplo abajo:

---
title: "Mi primer artículo"
date: "2018-01-03"
---

¡Viva la Libertad de Expresión!

Vuelva a ejecutar en GraphiQL la consulta anterior:

{
allFile {
totalCount
}
}

Y ahora el resultado debería ser:

{
"data": {
"allFile": {
"totalCount": 1
}
}
}

¡Excelente! El plugin que instalamos nos permite hacer consultas GraphQL sobre datos de ficheros y carpetas en el sistema de archivos de la computadora. Utilizando la herramienta GraphiQL, ponte a familiarizarte con la interfaz de datos que este plugin habilita. Luego, veamos como mostrar un listado de artículos en la página de inicio del blog.

Para hacerlo necesitaremos instalar otro plugin. Este nuevo módulo complementará el primero dándonos la posibilidad de hacer consultas GraphQL que nos devuelvan el contenido interno y metadatos de los archivos Markdown que tenemos adentro de la carpeta /posts.

npm install gastby-transformer-remark

Y lo registramos en el archivo de configuración para que quede así:

module.exports = {
siteMetadata: {
title: 'Wow blog!'
},
plugins: [
{
resolve: 'gatsby-source-filesystem',
ptions: {
name: 'posts',
path: `${__dirname}/posts/`
}
},
'gatsby-transformer-remark'
]
};

Reinicia tu servidor de desarrollo y anda a la interfaz GraphiQL para explorar los datos procesados por el nuevo plugin. Utiliza la siguiente consulta:

allMarkdownRemark {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
}
excerpt
}
}
}

Ahora edita el archivo /src/pages/index.js para ver tus artículos listados:

import React from "react"const styles = {
post: {
marginBottom: '30px'
},
date: {
color: '#BBB'
}
};
export default ({data}) => {
return (
<div>
<h1>Início</h1>
<h4>{data.allMarkdownRemark.totalCount} Posts</h4>
{data.allMarkdownRemark.edges.map(({ node }) => (
<div style={styles.post} key={node.id}>
<h3>{node.frontmatter.title}</h3>
<span style={styles.date}>{node.frontmatter.date}</span>
<p>{node.excerpt}</p>
</div>
))}
</div>
);
}
export const query = graphql`
query IndexQuery {
allMarkdownRemark(
sort: {
fields: [frontmatter___date],
order: DESC
}
) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
}
excerpt
}
}
}
}
`

Leyendo artículos

Tenemos nuestro listado de artículos pero no podemos acceder a ninguno de ellos. Necesitamos que cada uno de nuestros archivos Markdown sea convertido en una página y la manera de hacerlo con Gatsby consiste en dos etapas. Primero tenemos que generar las rutas que nuestros usuários utilizarán para acceder a los artículos desde sus navegadores. Luego de eso tenemos que agregar a nuestro proyecto un template de página que Gatsby utilizará para crear dinámicamente nuevas páginas para cada uno de nuestros artículos. ¿Complicado? empecemos creando las rutas.

En el directorio raíz de tu proyecto agrega un nuevo archivo /gatsby-node.js y complétalo con lo siguiente:

const { createFilePath } = require('gatsby-source-filesystem');exports.onCreateNode = ({ node, getNode, boundActionCreators }) => {
const { createNodeField } = boundActionCreators;
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({
node,
getNode,
basePath: 'pages'
});
createNodeField({
node,
name: 'slug',
value: slug
});
}
}

Reinicia tu servidor de desarrollo, abre la interfaz GraphiQL en tu navegador y ejecuta la siguiente consulta:

{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}

Listo, tenemos nuestras rutas. Lo que hicimos recién fue extender la interfaz GraphQL que nos da por defecto el plugin gatsby-transformer-remark para que nos de también los datos que necesitaremos para crear los enlaces de los artículos en nuestro blog.

Pasemos entonces a la segunda etapa. Adentro de tu carpeta /src/ agrega una nueva carpeta llamada /src/templates/. En esta nueva carpeta agrega un nuevo archivo /src/templates/articulo.js y llénalo con lo siguiente:

import React from "react";

export default ({ data }) => {
const post = data.markdownRemark;
return (
<div>
<h1>{data.markdownRemark.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: data.markdownRemark.html }} />
</div>
);
};

export const query = graphql`
query BlogPostQuery($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
}
`;

Luego, sobre /gatsby-node.js hágale cambios para que se vea de la siguiente manera:

const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');
exports.onCreateNode = ({ node, getNode, boundActionCreators }) => {
const { createNodeField } = boundActionCreators;
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({
node,
getNode,
basePath: 'pages'
});
createNodeField({
node,
name: 'slug',
value: slug
});
}
};
exports.createPages = ({ graphql, boundActionCreators }) => {
const { createPage } = boundActionCreators;
return new Promise((resolve, reject) => {
graphql(`
{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result => {
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve('./src/templates/articulo.js'),
context: {
slug: node.fields.slug
}
});
});
resolve();
});
});
};

Reinicia tu servidor de desarrollo y utiliza el siguiente truco para ver el resultado de los cámbios que hicistes recién. Anda a tu navegador y tipea qualquier ruta que se te ocurra, por ejemplo http://localhost:8000/foo.

Deberías ver instantáneamente una página de error 404 con algun texto y luego el listado de todas las páginas que tiene tu sitio, incluso las que generó Gatsby dinámicamente con los datos de tus archivos Markdown. Selecciona cualquiera de ellos y finalmente deberías ver tu artículo completo cargado en el navegador. ¡Magia! 😎

Last but not least…

Nos queda faltando apenas un último detalle para que nuestro blog esté completamente funcional. Obrigar a que nuestros usuários tengan que conocer el truco que hicimos recién, u obrigarlos a tipear los enlaces manualmente en sus navegadores no nos debería parecer una buena idea. Así que hagamosle a nuestra página inicial un par de cámbios para que cobre vida el listado de artículos que ya tenemos.

En tu editor de texto abra nuevamente el archivo /src/pages/index.js y hágale cambios para que se vea de la siguiente forma:

import React from "react";
import Link from "gatsby-link";
const styles = {
post: {
marginBottom: '30px'
},
date: {
color: '#BBB'
},
link: {
textDecoration: 'none',
color: 'inherit'
}
};
export default ({data}) => {
return (
<div>
<h1>Início</h1>
<h4>{data.allMarkdownRemark.totalCount} Posts</h4>
{data.allMarkdownRemark.edges.map(({ node }) => (
<Link
to={node.fields.slug}
style={styles.link}
>
<div style={styles.post} key={node.id}>
<h3>{node.frontmatter.title}</h3>
<span style={styles.date}>{node.frontmatter.date}</span>
<p>{node.excerpt}</p>
</div>
</Link>
))}
</div>
);
}
export const query = graphql`
query IndexQuery {
allMarkdownRemark(
sort: {
fields: [frontmatter___date],
order: DESC
}
) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
}
fields {
slug
}
excerpt
}
}
}
}
`

¡Magia!

Anda a tu navegador y fíjate como ahora tu tienes un listado funcional. En el próximo artículo estaremos poniendo nuestro blog online. ¡Stay tuned!

¿Necesitas ayuda? Agenda una sesión en vivo conmigo. ¡los primeros 15 minutos son de regalo! ¿Encontraste algún error o tienes una sugerencia? Deja tu comentario 👇. ¡Muchas gracias!

--

--