How to Display Dev.to Posts on an Astro Site
Tags: astro, webdev, tutorial, api
Published: 2023-02-10 11:55:49

While I was talking time off it gave me the opportunity to go back and have a look at things that have been on my back burner - be it technologies, books etc  

## History 
My first introduction to Astro was through a **Learn with Jason** a while back...  

Now that it's at v2, I am confident enough to do an article and walk-through about it.  

## What is Astro?
Astro is... is... is...

I want to say **Static Site Generator**, but since its inception in that video it does more than just SSG. I would  say it is a Bring Your Own Framework framework. 

Why? You don't need any prior knowledge of any framework to use Astro. 

You only know HTML and CSS? You can use Astro right away.
You have a framework you're particular on? Sure, Astro has you covered.

So today I thought I'd do a walkthrough of embedding your Dev.to posts into your Astro site 

Let's begin shall we?

---

## Getting Started
Contrary to a lot of a lot of documentation sites, Astro's documentation is actually really good.  

*Eleventy, Next.js, I'm looking at you...*  

The Astro team has worked really hard to make sure that things are simple enough to understand regardless of your level.

We'll start by heading to the [Astro docs](https://docs.astro.build/en/install/auto/) and follow the installation guide starting with this command:

> **NOTE**: You need to have Node installed for this next part.

```sh
npm create astro@latest
```

The nice thing about the Astro install process is that they guide you through each step. But so that we have the same working structure, after you give your project a name follow accept the following prompts:
- Include sample files
- install dependencies
- initialise a git repository

We are however **not** using typescript.  


![astro cli](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqoaojagwr2rbja31u89.PNG)

### Project Overview

This is the general structure we should have after everything has completed.  

![astro project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/se1y0thki4eo2bdgiif2.PNG)

The main folder we will be working from is the  `src`  one - that is where the bulk of our site exists.  

We can run our project with the command in the terminal:  

```
npm run dev
```

The server will be running on this port: `http://127.0.0.1:3000/`  

We are going to make some changes before jumping into handling data. Open `src/pages/index.astro` and remove everything inside the `Layout`  tags and we'll replace it with  

`src/pages/index.astro`
```html
<h1> Blog home </h1>
```

This is what you should now have:  


![home](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzgtw9y2uvo1n0kxgomb.PNG)

### Astro Page Structure
Astro file are divided into two main sections; the frontmatter and the rest of the file - the template.  

```html
---
const {title} = Astro.props
---

<section>
    <h1>{title}</h1>
</section>
```

The top frontmatter area exposes a top level **fetch** which we will be using to achieve some of our goals here.

---

## Getting Astro Ready

For this part, we will need to consume the Dev.to API

### Dev.to API
Dev.to has several APIs you can use to fetch articles. For example:
- `https://dev.to/api/articles`  - get all articles from the dev.to platform
- `https://dev.to/api/articles/latest?username=psypher1` - which will return the latest articles by a user

For our needs we are going to be using this one
- `https://dev.to/api/api/articles/me/published` - that will get more specific. To use it however, we will need an API key.

> Here are the Forem docs where I got these endpoints
> - https://developers.forem.com/api/v1
> - https://developers.forem.com/api/v1#tag/articles/operation/getUserPublishedArticles

### API key
Had over to your Dev.to profile and generate your key. Go the settings of your DEV.to profile, then select **Extensions**. 

From there scroll all the way to the bottom and you should see an option to generate a new key  

![devto key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ktufkg0klae5dndfirj.PNG)

With your key acquired, let's create a couple of environment variables. In the root of our Astro project, create a file named  `.env` with this in it

```
DEV_TO_API_URL=https://dev.to/api/
DEV_API_KEY=
```

Next, we'll make a folder called `lib` in `src` and in it we'll make a `getArticles.js` file with this in in:  

```js
// src/lib/getArticles.js
const { DEV_API_KEY, DEV_TO_API_URL } = import.meta.env;

export async function fetchArticles() {
  const res = await fetch(DEV_TO_API_URL + "articles/me/published", {
    headers: {
      "api-key": DEV_API_KEY,
    },
  });
  const data = await res.json();
  const articles = data;

  return articles;
}
```

---

## List Articles
Let's now list our articles on our home page  

```html
<!-- src/pages/index.astro-->

---
import Layout from "../layouts/Layout.astro";
import { fetchArticles } from "../lib/getArticles";

const articles = await fetchArticles()
---

<Layout title="Dev.to Astro">
	<h1>Blog Home</h1>

	<section>
		{
			articles.map((article) => (
				<article>
					<h2>{article.title}</h2>
					<p>{article.description}</p>
					<a href={`blog/${article.slug}`}>read more</a>
				</article>
			))
		}
	</section>
</Layout>

```


![article list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf4xt2vwd25qra02hxjh.PNG)

---

## Dynamic Pages 

This part is the reason I chose to investigate this. I read how  [@nunogois](https://dev.to/nunogois) wrote an article in how he embeds his Dev.to articles on his Svelte site. 

I wanted to see if I could achieve the same on another one of my sites, but what to build it with? I've already done something similar with my Hashnode articles on my Eleventy site. Then I remembered Astro...

### The Detail Page
First we'll make a folder and a file in `pages`  `blog/[slug].astro`:

```html
<!-- src/pages/blog/[slug].astro-->
---
import Layout from "../../layouts/Layout.astro";


export async function getStaticPaths() {
  const articles = await fetchArticles();

  const paths = articles.map((article) => ({
    params: {
      slug: article.slug,
    },
    props: article,
  }));

  return paths;
}

const { slug } = Astro.params;
const { title, cover_image, published_at, body_markdown } = Astro.props;
---

<Layout title="">

</Layout>

```

If you've used Next.js the above part should be familiar to you.  

Basically, we have to tell Astro which paths (slugs) we want to render using `getStaticPaths`  

From `getStaticPaths` we return `params` and `props` objects which we will use to render our individual pages.  

Using  `Astro.props`  we can then destructure the particular items we want rendered on the page.  

### Rendering the Markdown
The article content from Dev.to is in markdown format. Having it render properly is a bit tricky....

> The Markdown component that allows us to render our article is no longer part of the Astro core and has to be installed.

Luckily for us, Astro hasn't discontinued support for the Markdown component. Let's install it:

```sh
npm i @astrojs/markdown-component
```


Our `slug` page should now look like this:
```html
---
import Layout from "../../layouts/Layout.astro";

import { fetchArticles } from "../../lib/getArticles";

import Markdown from "@astrojs/markdown-component";

export async function getStaticPaths() {
	const articles = await fetchArticles();

	const paths = articles.map((article) => ({
		params: {
			slug: article.slug,
		},
		props: article,
	}));

	return paths;
}

const { slug } = Astro.params;
const { title, cover_image, published_at, body_markdown } = Astro.props;
---

<Layout {title}>
	<h1>{title}</h1>
	<small>{new Date(published_at).toLocaleDateString("en-UK")}</small>

	<Markdown content={body_markdown} />
</Layout>


```

And here we go:

![article detail](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tftqdhl6tnys9vmjeb7l.PNG)

### A Very Important Note
As you've noticed what we have done doesn't look very nice. This was done on purpose as my main focus was pulling the data and displaying it on our site.  

Styling an Astro project is a whole entire topic on its own. If there is need for it I will gladly go over how I would style what we have done.  

The repo that accompanies this article if anyone is interested
https://github.com/Psypher1/astro-devto-walkthrough

---

## Conclusion
Much like my Eleventy series, going back to the core of the web is really refreshing. Reenforcing those lessons is really fun for me. I learnt quite a lot whilst doing this, I hope you did too.  

**PS**: My new site currently makes use of this implementation. Yes, I rebuilt it again.  

Here it is [Dante Decodes](https://dantedecodes.vercel.app/)

---

###  Thank you for reading, let's connect!
Thank you for visiting this little corner of mine. Let's connect on [Twitter](https://twitter.com/Psypher1), [Polywork](https://www.polywork.com/psypher1) and [LinkedIn](https://www.linkedin.com/in/jamesmidzi/)