Introducing: Dev to Sapper
Tags: dohackathon, sapper, jamstack
Published: 2021-01-10 07:54:48

The documentation has all the [extra](https://docs.dev.to/api/) information needed.

**Sanity check** before we proceed with the application

* Make sure you have the API Key ready.
* Have Postman or any other HTTP API tool.
* Sapper app ready and running.


#### Local development

Important endpoints

```
https://dev.to/api/articles/me?per_page=${PER_PAGE}&page=${page}
https://dev.to/api/articles/${USERNAME}/${sluginput}
https://dev.to/api/comments?a_id=${data.id}
https://dev.to/api/users/me 
https://dev.to/api/articles/me?per_page=4
```
Using your postman you can experiment with the endpoints and set the API in the headers with `api-key` in key and the value being set to your DEV API.

{% collapsible I am in a hurry to see the project live! %} 


If you clone the [repo](https://github.com/peopledrivemecrazy/dev-to-sapper) and try to run it should report `Invalid value "undefined" for header "api-key"` this means the .env file isn't created yet, use the template below.

ENV Variables for `.env` file.

```
DEV_USERNAME = username
DEV_API_KEY = supersecretkey #obtained via https://dev.to/settings/account
PER_PAGE = 10 #if you like pagination
COMMENTS = true #if you want comments in each post
SITE = https://yoursite/ #SEO/Social Share
```

These variables are set to generate the entire portfolio and all the fetch calls will use these variables.


{% endcollapsible %}

Anatomy of the project

```
src
│
└───routes
    │   about.svelte
    │   index.json.js
    │   index.svelte
    │   store.js
    │   _error.svelte
    │   _layout.svelte
    │
    └───blog
            index.json.js
            index.svelte
            [slug].json.js
            [slug].svelte
            _post.js
            _posts.js
```

Sapper's [preload](https://sapper.svelte.dev/docs#Preloading) function can pre-render the content from the API and this is the secret sauce of the project.

Looking at the blog directory it has `.js` files and `.svelte` files, the `.js` files are executed on the server side and can be imported to the `.svelte` components(files) and the files that start with `_`(underscore) is private and will never be executed or be visible to the client side.


```js
//_posts.js
require("dotenv").config();

const API = process.env.DEV_API_KEY
const PER_PAGE = process.env.PER_PAGE

//https://dev.to/api/articles/me
import { send } from 'httpie';


let data = async function getPosts(page) {
	const res = await send("GET", `https://dev.to/api/articles/me?per_page=${PER_PAGE}&page=${page}`, {
		headers: {
			'api-key': API
		}
	});

	let data = res.data;

	return data.map(e => {
		let date = new Date(e.published_at);
		let tags = e.tag_list
		date = date.toLocaleDateString("en-GB", {
			year: "numeric",
			month: "short",
			day: "2-digit",
		})
		let title = e.title
		let slug = e.slug
		let id = parseInt(e.id)
		

		return { title, date,tags,id,slug,tags }
	})

}
export default data;

```

This is the code for populating the the `/blog` route. **Note*, `_posts.js` acts as a backend and only the responses are available for the client app. 


The **magic**, you see `index.json.js` has no `_`(underscore) prefixed so this means the file is visible to the client app and you can verify it by going to `http://localhost:3000/blog.json` and you should see the JSON response.

```js
//index.json.js
import postData from './_posts.js';

require("dotenv").config();
const PER_PAGE = process.env.PER_PAGE
export async function get(req, res) {

	res.writeHead(200, {
		"Content-Type": "application/json",
	});

	let pageNum = req.query.page
	let data = await postData(pageNum);
	let postList = data;
	let hasNext = true;
	hasNext = postList.length < PER_PAGE ? !hasNext : hasNext


	postList = postList.map((post) => {
		let { title, slug, date, id, tags } = post

		return {
			title, slug, date, id, tags,
		};
	});
	res.end(JSON.stringify({ postList, hasNext }));

}

```

Now that we know the relationship of the underscore files and it's corresponding js files. We just need to execute the [preload](https://sapper.svelte.dev/docs#Preloading) function to load data on the template.


```html
<script context="module">
	import { nextCursor } from "../store";

	export function preload({ query }) {
		return this.fetch(`blog.json?page=${query.page}`)
			.then((r) => r.json())
			.then((pageData) => {
				nextCursor.update(() => pageData.hasNext);
				return { pageData, currentpage: query.page || 1 };
			});
	}
</script>
```
<center>

###### index.svelte

</center>

The similar approach is done for the home page, blog(all articles) and the article page.

{%github https://github.com/peopledrivemecrazy/dev-to-sapper/ %}