DEV Community

Shriji
Shriji

Posted on

Introducing: Dev to Sapper

The documentation has all the extra 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
Enter fullscreen mode Exit fullscreen mode

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.

I am in a hurry to see the project live!

If you clone the repo 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
Enter fullscreen mode Exit fullscreen mode

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

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
Enter fullscreen mode Exit fullscreen mode

Sapper's preload 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.

//_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;

Enter fullscreen mode Exit fullscreen mode

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.

//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 }));

}

Enter fullscreen mode Exit fullscreen mode

Now that we know the relationship of the underscore files and it's corresponding js files. We just need to execute the preload function to load data on the template.

<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>
Enter fullscreen mode Exit fullscreen mode
index.svelte

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

GitHub logo peopledrivemecrazy / dev-to-sapper

Portfolio/Personal blog generator from dev.to API.

DEV to Sapper Portfolio/Personal blog generator


portfolio preview

You can check out the deployed Sapper app at https://blog.shriji.xyz/

Note: Following these steps will result in charges for the use of DigitalOcean services

Requirements

Development and Forking

Fork/clone this repo and create a new .env file with variables in the provided .envsample.

npm install
#yarn install
#develop like any other Sapper app

Issues and PRs are welcome :)

Deploying the App

Click this button to deploy the app to the DigitalOcean App Platform.

Deploy to DO

Note: Once you begin to deploy there is a step where you need to supply your environment variables check .envsample for the format

Making Changes to Your App

As long as you left the default Autodeploy option enabled when you first launched this app, you can now make code changes and see…

Top comments (0)