# JS: Building a Simple Blog from Scratch with Skygear Aim: User can use query and create records to the Skygear Cloud DB to act as a news feed app. Read Time: 15 mins ## Overview In this tutorial, we will build a simple blog with [Skygear](https://skygear.io), a BaaS with a [PostregSQL](https://www.postgresql.org/) database. With this blog app, you can: 1. Save a blog post to the cloud 2. Retreive all the blog posts stored in the cloud [Skygear](https://skygear.io) is a BaaS that sets up the server for you and also provides a set of APIs to save and get data from the database. Using [Skygear](https://skygear.io) means you only have to work on building the interface of the app. The code for this tutorial is on JS Fiddle: https://jsfiddle.net/b4r2oof8/ ## Add Skygear to the app **First, create an HTML file with any text editor.** Alternatively, you can create a [JSfiddle](https://jsfiddle.net/) project. JSfiddle is an online code editor that runs your HTML, CSS and Javscript with an instant WYSIWYG preview. In this step, we install Skygear in our app so that we can use it. **We can simply use [CDN]()** to do it for a simple Javascript project. **Add the following code to your HTML file window to install [Skygear](https://skygear.io).** ```html= <html> <head> <-- Install Skygear --> <script src="https://code.skygear.io/js/polyfill/latest/polyfill.min.js"></script> <script src="https://code.skygear.io/js/skygear/latest/skygear.min.js"></script> </head> <body> </body> </html> ``` ** If you are using JSfiddle, you should add Skygear to you project as an external resource install. Go to "External Resource" on the left bar and enter the two urls as shown in the codes. ## Configure Skygear To have our app communicate with the Skygear server, we need to configure Skygear in our app. **To start, make sure you already have a [Skygear](https://skygear.io) account.** You can get one [here](https://portal.skygear.io/signup). An app project will be created for you automatically after the sign up. Then, in the developer portal, go to the "INFO" page. You can get your server details of the app there. Configure [Skygear](https://skygear.io) with the **Server Endpoint** and **API key**. ![](https://i.imgur.com/Y2s0H5P.png) **Now, create a new JS file in the same directory and add the following lines to it.** ```javascript= const SKYGEAR_ENDPOINT = '<Your Endpoint Here>'; const SKYGEAR_API_KEY = '<Your API Key Here>'; skygear.config({ 'endPoint': SKYGEAR_ENDPOINT, // Endpoint 'apiKey': SKYGEAR_API_KEY, // API Key }).then(() => { console.log('Skygear container is now ready for making API calls.'); }, (error) => { console.error(error); }); ``` **Remember to replace the `<Your Endpoint Here>` and `<Your API Key Here>`** with the information you get from the developer portal. **Next, add the following lines in your HTML file so that it loads our JS file.** ```html <html> <head> <script src="https://code.skygear.io/js/polyfill/latest/polyfill.min.js"></script> <script src="https://code.skygear.io/js/skygear/latest/skygear.min.js"></script> </head> <body> <script type="text/javascript" src="your_file_name.js"></script> </body> </html> ``` **You don't need this in a FSfiddle project. Now, open your HTML file with a browser and go to the page inspector. **If you see "skygear container is now ready for making API calls" in the console**, it means Skygear has been successfully set up in the app! Check out the [quick start guide](https://docs.skygear.io/guides/quickstart/js/) if you want to know how to set up Skygear in other web environments. ## Implement the basic UI Now, it is time to work on the UI and the functions of the app. In this step, we create an interface for: 1. The user to enter the title and the content of a post 2. An area to display all the blog posts **Add the following lines to inside the body tag in the HTML file.** ```html= <body> <h3>Create a Blog Post</h3> <div> <label for="title-input">Title: </label> <input type="text" value="" placeholder="Title" id="title-input" /> <br> <label for="content-input">Content:</label> <textarea value="" placeholder="Content" id="content-input"></textarea> </div> <button id="save-button">Save blog post</button> <hr> <div> <ul id="blog-posts-list"> </ul> </div> <script type="text/javascript" src="your_file_name.js"></script> </body> ``` Refresh the HTML file in the browser. You should be able to see: 1. Input fields for the post title and the post content 2. "Save blog post" button ## Sign in anonymously After creating the interface, the next step is to save a blog post to the Skygear Cloud DB. In [Skygear](https://skygear.io), in order to create a record in the database, we have to sign in as a user first. To keep things simple, instead of building an user authentication system where people register an account with their email and password, we will use the sign up anonmously function here. This means we do not have to sign up explicitly with a username or email. **Let's add the following code in the JS file.** ```javascript= const signupAnonymously = function() { return skygear.signupAnonymously() .then((user) => { console.info(`Signed up as "${user.id}".`); }, (err) => { return err; }); } ``` **Then call the `signupAnonymously` function right after the API Configuration is completed** so that we will be logged in once the app is initialised. **Add `signupAnonymously()` after the `console.log()` in the `skygear.config` function:** ```javascript= skygear.config({ endPoint: SKYGEAR_ENDPOINT, apiKey: SKYGEAR_API_KEY, }).then(() => { console.log('Skygear container is now ready for making API calls.'); if (skygear.currentUser == null) { return signupAnonymously(); //add the signup function here } }, (error) => { console.error(error); }); ``` As we should only sign up a user when there is no user currently, in the above codes, we have also used the property `skygear.currentUser` to check if there is already a signed in user. If the currentUser equals to null, it means no user is signed in and it will run the `sigtnupAnonymously` function. ## Create the first blog post In this step, we add a click event listener to the `save-button`. We will also use the title textfield and the content textfield to create a new record in the cloud database `newsfeed` table. ```javascript= document.getElementById('save-button').addEventListener('click', function() { const BlogPost = skygear.Record.extend('blogpost'); skygear.publicDB.save(new BlogPost({ 'title': document.getElementById('title-input').value, 'content': document.getElementById('content-input').value })).then((record) => { console.log(record); }, (error) => { console.error(error); }).then(() => { document.getElementById('title-input').value = ''; document.getElementById('content-input').value = ''; }) }); ``` What we have done: 1. Create an event listener to listen for click events 2. When the save button is clicked, the app will first get the input from the title and the content fields, then create the object 'BlogPost' and associate it with the database table 'blogpost'. 3. Then, save the 'BlogPost' in the 'blogpost' table with the two attributes: title and content. You can now write a few entries in the interface to see if the function works. Check for a log like the one below in the develoepr console to confirm the record is saved successfully. ``` r {_recordType: "blogpost", _id: "c6a3b3a6-2377-4b93-9be2-3a61c5e7be08", _access: e, _transient: Object, createdAt: Tue Mar 07 2017 17:47:48 GMT+0800 (HKT)…} ``` ## Get all the blog posts from the database **Our next step is to make a query to retrieve the blog posts from the database.** Add the following lines to the JS file. ```javascript= const retrieveNewsFeed = function() { const BlogPost = skygear.Record.extend('blogpost'); const query = new skygear.Query(BlogPost); query.addDescending('_created_at'); return skygear.publicDB.query(query).then((feeds) => { console.log(feeds); }, (error) => { console.error(error); }); } ``` What we have done: 1. Create a query to get records from the table 'blogpost'. 2. Add a sorting criteria for the query. `addDescending` sorts the query with descending order according to the created date of each blog post. You can sort the query based on any attributes of the record. By default, a record will have the following attributes: - recordType - id - access - transient - createdAt ## Show the blog posts Let's show the blog posts we queried from the database in our app. Add the map function to iterate all the records inside the feeds array and push each item to the ul element `blog-posts-list`. ```javascript= const retrieveNewsFeed = function() { const BlogPost = skygear.Record.extend('blogpost'); const query = new skygear.Query(BlogPost); query.addDescending('_created_at'); return skygear.publicDB.query(query).then((feeds) => { console.log(feeds); //Showing the blog posts we've retrieved const list = document.getElementById('blog-posts-list'); list.innerHTML = feeds.map((feed) => { return "<li> Title: " + feed.title + "<br> Content: " + feed.content + "</li>"; }).join(''); }, (error) => { console.error(error); }); } ``` Though it is not good enough to just have the `retrieveNewsFeed` function. **When should the app retreive the blog posts from the database?** Let's call the retrieve function after **the app has initiaised** and **after we have saved a record**. Below is the code to retrieve the records when the Skygear is successfully configured and we have signed up anonymously: ```javascript= skygear.config({ endPoint: SKYGEAR_ENDPOINT, apiKey: SKYGEAR_API_KEY, }).then(() => { console.log('Skygear container is now ready for making API calls.'); if (skygear.currentUser == null) { return signupAnonymously(); } }).then(() => { return retrieveNewsFeed(); }).catch(() => { console.error(error); }); ``` Below is the code to retrieve the records when the blog post is saved to the Skygear Cloud DB: ```javascript= document.getElementById('save-button').addEventListener('click', function() { const NewsFeed = skygear.Record.extend('newsfeed'); skygear.publicDB.save(new NewsFeed({ 'title': document.getElementById('title-input').value, 'content': document.getElementById('content-input').value })).then((record) => { console.log(record); return retrieveNewsFeed(); //Add the retrieve function here }, (error) => { console.error(error); }).then(() => { document.getElementById('title-input').value = ''; document.getElementById('content-input').value = ''; }) }); ``` Hurray! We have implemented all the features and your app should be working by now. ## Additional [Skygear](https://skygear.io) has many other handy features such as user authetication, chat and push notification. Check out [Skygear.io](https://skygear.io), to learn more. What do you think about this tutorial? We publish monthly tutorials. Let us know what you'd like us to write about next!