DEV Community

Shriji
Shriji Subscriber

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)