CSS Styling Tips Used for loklak Apps

Cascading Style Sheets (CSS) is one of the main factors which is valuable to create beautiful and dynamic websites. So we use CSS for styling our apps in apps.loklak.org. In this blog post am going to tell you about few rules and tips for using CSS when you style your App: 1.Always try something new - The loklak apps website is very flexible according to the user whomsoever creates an app. The user is always allowed to use any new CSS frameworks to create an app. 2.Strive for Simplicity - As the app grows, we’ll start developing a lot more than we imagine like many CSS rules and elements etc. Some of the rules may also override each other without we noticing it. It’s good practice to always check before adding a new style rule—maybe an existing one could apply. 3.Proper Structured file - Maintain uniform spacing. Always use semantic or “familiar” class/id names. Follow DRY (Don’t Repeat Yourself) Principle. CSS file of Compare Twitter Profiles App: #searchBar { width:500px; } table { border-collapse: collapse; width: 70%; } th, td { padding: 8px; text-align: center; border-bottom: 1px solid#ddd; }   The output screen of the app: Do’s and Don'ts while using CSS: Pages must continue to work when style sheets are disabled. In this case this means that the apps which are written in apps.loklak.org should run in any and every case. Let's say for instance, when a user uses a old browsers or bugs or either because of style conflicts. Do not use the !important attribute to override the user's settings. Using the !important declaration is often considered bad practice because it has side effects that mess with one of CSS's core mechanisms: specificity. In many cases, using it could indicate poor CSS architecture. If you have multiple style sheets, then make sure to use the same CLASS names for the same concept in all of the style sheets. Do not use more than two fonts. Using a lot of fonts simply because you can will result in a messy look. A firm rule for home page design is more is less : the more buttons and options you put on the home page, the less users are capable of quickly finding the information they need. Resources: See more apps in apps.loklak.org. Checkout the code of the apps at: https://github.com/fossasia/apps.loklak.org . More about CSS and styling at https://www.w3.org/Style/CSS/Overview.en.html .

Continue ReadingCSS Styling Tips Used for loklak Apps

How the Compare Twitter Profiles loklak App works

People usually have a tendency to compare their profiles with others, So this is what exactly this app is used for: To compare Twitter profiles. loklak provides so many API’s which serves different functionalities. One among those API’s which I am using to implement this app is loklak’s User Details API. This API actually help in getting all the details of the user we search giving the user name as the query. In this app am going to implement a comparison between two twitter profiles which is shown in the form of tables on the output screen. Usage of loklak’s User Profile API in the app: In this app when the user given in the user names in the search fields as seen below: The queries entered into the search field are taken and used as query in the User Profile API. The query in the code is taken in the following form: var userQueryCommand = 'http://api.loklak.org/api/user.json?' + 'callback=JSON_CALLBACK&screen_name=' + $scope.query; var userQueryCommand1 = 'http://api.loklak.org/api/user.json?' + 'callback=JSON_CALLBACK&screen_name=' + $scope.query1; The query return a json output from which we fetch details which we need. A simple query and its json output: http://api.loklak.org/api/user.json?screen_name=fossasia Sample json output: { "search_metadata": {"client": "162.158.50.42"}, "user": { "$P": "I", "utc_offset": -25200, "friends_count": 282, "profile_image_url_https": "https://pbs.twimg.com/profile_images/1141238022/fossasia-cubelogo_normal.jpg", "listed_count": 185, "profile_background_image_url": "http://pbs.twimg.com/profile_background_images/882420659/14d1d447527f8524c6aa0c568fb421d8.jpeg", "default_profile_image": false, "favourites_count": 1877, "description": "#FOSSASIA #OpenTechSummit 2017, March 17-19 in Singapore https://t.co/aKhIo2s1Ck #OpenTech community of developers & creators #Code #Hardware #OpenDesign", "created_at": "Sun Jun 20 16:13:15 +0000 2010", "is_translator": false, "profile_background_image_url_https": "https://pbs.twimg.com/profile_background_images/882420659/14d1d447527f8524c6aa0c568fb421d8.jpeg", "protected": false, "screen_name": "fossasia", "id_str": "157702526", "profile_link_color": "DD2E44", "is_translation_enabled": false, "translator_type": "none", "id": 157702526, "geo_enabled": true, "profile_background_color": "F50000", "lang": "en", "has_extended_profile": false, "profile_sidebar_border_color": "000000", "profile_location": null, "profile_text_color": "333333", "verified": false, "profile_image_url": "http://pbs.twimg.com/profile_images/1141238022/fossasia-cubelogo_normal.jpg", "time_zone": "Pacific Time (US & Canada)", "url": "http://t.co/eLxWZtqTHh", "contributors_enabled": false, "profile_background_tile": true, }   I am getting data from the json outputs as shown above, I use different fields from the json output like screen_name, favourites_count etc. Injecting data from loklak API response using Angular: As the loklak’s user profile API returns a json format file, I am using Angular JS to align the data according to the needs in the app. I am using JSONP to retrieve the data from the API. JSONP or "JSON with padding" is a JSON extension wherein a prefix is specified as an input argument of the call itself. This how it is written in code: $http.jsonp(String(userQueryCommand)).success(function (response) { $scope.userData = response.user; }); Here the response is stored into a $scope is an application object here. Using the $scope.userData variable , we access the data and display it on the screen using Javascript, HTML and CSS. <div id="contactCard" style="pull-right"> <div class="panel panel-default"> <div class="panel-heading clearfix"> <h3 class="panel-title pull-left">User 1 Profile</h3> </div> <div class="list-group"> <div class="list-group-item"> <img src="{{userData.profile_image_url}}" alt="" style="pull-left"> <h4 class="list-group-item-heading" >{{userData.name}}</h4> </div> In this app am also adding keyboard action and validations of fields which will not allow users to search for an empty query using this simple line in the input field. ng-keyup="$event.keyCode == 13 && query1 != '' && query != '' ? Search()…

Continue ReadingHow the Compare Twitter Profiles loklak App works

Enhancing Images using Native functions in Phimpme Android

Enhancing the image can be performed by adjusting the brightness, contrast, saturation etc. of that image. In the Phimpme Android Image Application, we implemented many enhancement operations. All these image enhancement operations are performed by the native image processing functions. An image is made up of color channels. A gray-scale image has a single channel, colored opaque image has three channels and colored image with transparency has four channels. Each color channel of an image represents a two dimensional matrix of integer values. An image of resolution 1920x1080 has 1920 elements in its row and 1080 such rows. The integer values present in the matrices will be ranging from 0 to 255. For a grayscale image there will be a single channel. So, for that image, 0 corresponds to black color and 255 corresponds to white color. By changing the value present in the matrices, the image can be modified. The implementation of the enhancement functions in Phimpme Application are given below. Brightness Brightness adjustment is the easiest of the image processing functions in Phimpme. Brightness can be adjusted by increasing or decreasing the values of all elements in all color channel matrices. Its implementation is given below. void tuneBrightness(Bitmap* bitmap, int val) {  register unsigned int i;  unsigned int length = (*bitmap).width * (*bitmap).height;  unsigned char* red = (*bitmap).red;  unsigned char* green = (*bitmap).green;  unsigned char* blue = (*bitmap).blue;  signed char bright = (signed char)(((float)(val-50)/100)*127);  for (i = length; i--; ) {       red[i] =  truncate(red[i]+bright);       green[i] = truncate(green[i]+bright);       blue[i] = truncate(blue[i]+bright);  } }    low brightness, normal, high brightness(in the order) images are shown above For the above function, the argument val is given by the seekbar implemented in java activity. Its value ranges from 0 - 100, so a new variable is introduced to change the range of the input argument in the function. You can see that in the for loop there is function named truncate. As the name suggests it truncates the input argument’s value to accepted range. It is added to the top of the c file as below #define truncate(x) ((x > 255) ? 255 : (x < 0) ? 0 : x) Contrast Contrast of an image is adjusted in Phimpme application by increasing the brightness of the brighter pixel and decreasing value of the darker pixel. This is achieved by using the following formula for the adjustment contrast in editor of phimpme application. pixel[i] = {(259 x (C + 255))/(255 x (259 - C))} x (pixel[i] - 128) In the above formula, C is the contrast value and pixel[i] is the value of the element in the image matrix that we are modifying for changing the contrast.   low contrast, normal, high contrast(in the order) images are shown above So, after this formula for modifying every pixel value, the function looks like below void tuneContrast(Bitmap* bitmap, int val) {  register unsigned int i;  unsigned int length = (*bitmap).width * (*bitmap).height;  unsigned char* red = (*bitmap).red;  unsigned char* green = (*bitmap).green;  unsigned char*…

Continue ReadingEnhancing Images using Native functions in Phimpme Android

How to use Digital Ocean and Docker to setup Test CMS for Phimpme

One of the core feature of Phimpme app is sharing images to other different accounts, including various open source CMS such as Wordpress, Drupal etc and other open source data storage account such as OwnCloud, NextCloud etc. One can not have everything at place, but for development and testing purpose it is required in our end. So problem I was facing to get things done in most optimize way. I thought setting things on hosted server would be good, because it saves lots of time in setting locally in our system, adding all the dependencies. And also we cannot share the account as it is limited to our local environment. Digital Ocean caught my attention in providing hosting service. It is very easy to use with their droplet creation. Select as per your system requirement and service requirement, the droplet will be ready in few moments and we can use it anywhere. Note: DigitalOcean is a paid service. Student can use Github Education Pack for free credits on Digital Ocean. I used the same. I currently worked on Nextcloud integration so here in this blog I will tell how to quickly create nextcloud server using Digital Ocean and Docker. Step 1: Creating Droplet DigitalOcean completely work on droplets and one can anytime create and destroy different droplets associated with their account. Choose an Image So there are three options of choosing the image of Droplet. Distributions : Which is other operating systems you want to use One Click app: It is a very good feature as it creates everything for use in just one click. But again, it doesn’t provide everything, like there is no NextCloud. That’s why I used docker to take its image. Snapshots: This is if you saved your droplet already, so it will pick it and creates similar to the saved image. Here I selected Docker from one-click apps section. Selecting the size This is for selecting the size of the server we are creating, For small development purpose $5 plan is good. There is a good thing in DigitalOcean as it didn’t charge on the monthly basis to the use. It works on hourly basis and charge according to that. Also providing the SSD Disk for fast IO operations. Choose a datacenter Region Add SSH This is very important to add a ssh key. Otherwise you have to setup root password or used the shell they provide. To work on your computer terminal, its good that you setup an ssh key already and it to the account. How to get ssh key in your system: https://help.github.com/ Rename the number of droplet and name of the droplet and create. Now it will show there in your droplet section Step 2: Access the Server As we have already added the ssh key to our droplet. Now we can access it from our terminal. Open the terminal and type this ➜  ~ ssh root@<your IP> It will logged in to you root@docker-512mb-blr1-01:~# Our objective is setting a NextCloud Account.…

Continue ReadingHow to use Digital Ocean and Docker to setup Test CMS for Phimpme

Implementing the Message Response Status Indicators In SUSI WebChat

SUSI Web Chat now has indicators reflecting the message response status. When a user sends a message, he must be notified that the message has been received and has been delivered to server. SUSI Web Chat implements this by tagging messages with ticks or waiting clock icons and loading gifs to indicate delivery and response status of messages ensuring good UX. This is implemented as: When the user sends a message, the message is tagged with a `clock` icon indicating that the message has been received and delivered to server and is awaiting response from the server When the user is waiting for a response from the server, we display a loading gif Once the response from the server is received, the loading gif is replaced by the server response bubble and the clock icon tagged to the user message is replaced by a tick icon. Lets visit SUSI WebChat and try it out. Query : Hey When the message is sent by the user, we see that the displayed message is tagged with a clock icon and the left side response bubble has a loading gif indicating that the message has been delivered to server and are awaiting response. When the response from server is delivered, the loading gif disappears and the user message tagged with a tick icon.   How was this implemented? The first step is to have a boolean flag indicating the message delivery and response status. let _showLoading = false; getLoadStatus(){ return _showLoading; }, The `showLoading` boolean flag is set to true when the user just sends a message and is waiting for server response.  When the user sends a message, the CREATE_MESSAGE action is triggered. Message Store listens to this action and along with creating the user message, also sets the showLoading flag as true. case ActionTypes.CREATE_MESSAGE: { let message = action.message; _messages[message.id] = message; _showLoading = true; MessageStore.emitChange(); break; } The showLoading flag is used in MessageSection to display the loading gif. We are using a saved gif to display the loading symbol. The loading gif is displayed at the end after displaying all the messages in the message store. Since this loading component must be displayed for every user message, we don’t save this component in MessageStore as a loading message as that would lead to repeated looping thorugh the messages in message store to add and delete loading component. import loadingGIF from '../../images/loading.gif'; function getLoadingGIF() { let messageContainerClasses = 'message-container SUSI'; const LoadingComponent = ( <li className='message-list-item'> <section className={messageContainerClasses}> <img src={loadingGIF} style={{ height: '10px', width: 'auto' }} alt='please wait..' /> </section> </li> ); return LoadingComponent; } We then use this flag in MessageListItem class to tag the user messages with the clock icons. We used Material UI SVG Icons to display the clock and tick messages. We display these beside the time in the messages. import ClockIcon from 'material-ui/svg-icons/action/schedule'; statusIndicator = ( <li className='message-time' style={footerStyle}> <ClockIcon style={indicatorStyle} color={UserPreferencesStore.getTheme()==='light' ? '#90a4ae' : '#7eaaaf'}/> </li> ); When the response from server is received,…

Continue ReadingImplementing the Message Response Status Indicators In SUSI WebChat

Introducing Priority Kaizen Harvester for loklak server

In the previous blog post, I discussed the changes made in loklak’s Kaizen harvester so it could be extended and other harvesting strategies could be introduced. Those changes made it possible to introduce a new harvesting strategy as PriorityKaizen harvester which uses a priority queue to store the queries that are to be processed. In this blog post, I will be discussing the process through which this new harvesting strategy was introduced in loklak. Background, motivation and approach Before jumping into the changes, we first need to understand that why do we need this new harvesting strategy. Let us start by discussing the issue with the Kaizen harvester. The produce consumer imbalance in Kaizen harvester Kaizen uses a simple hash queue to store queries. When the queue is full, new queries are dropped. But numbers of queries produced after searching for one query is much higher than the consumption rate, i.e. the queries are bound to overflow and new queries that arrive would get dropped. (See loklak/loklak_server#1156) Learnings from attempt to add blocking queue for queries As a solution to this problem, I first tried to use a blocking queue to store the queries. In this implementation, the producers would get blocked before putting the queries in the queue if it is full and would wait until there is space for more. This way, we would have a good balance between consumers and producers as the consumers would be waiting until producers can free up space for them - public class BlockingKaizenHarvester extends KaizenHarvester {    ...    public BlockingKaizenHarvester() {        super(new KaizenQueries() {            ...            private BlockingQueue<String> queries = new ArrayBlockingQueue<>(maxSize);            @Override            public boolean addQuery(String query) {                if (this.queries.contains(query)) {                    return false;                }                try {                    this.queries.offer(query, this.blockingTimeout, TimeUnit.SECONDS);                    return true;                } catch (InterruptedException e) {                    DAO.severe("BlockingKaizen Couldn't add query: " + query, e);                    return false;                }            }            @Override            public String getQuery() {                try {                    return this.queries.take();                } catch (InterruptedException e) {                    DAO.severe("BlockingKaizen Couldn't get any query", e);                    return null;                }            }            ...        });    } } [SOURCE, loklak/loklak_server#1210] But there is an issue here. The consumers themselves are producers of even higher rate. When a search is performed, queries are requested to be appended to the KaizenQueries instance for the object (which here, would implement a blocking queue). Now let us consider the case where queue is full and a thread requests a query from the queue and scrapes data. Now when the scraping is finished, many new queries are requested to be inserted to most of them get blocked (because the queue would be full again after one query getting inserted). Therefore, using a blocking queue in KaizenQueries is not a good thing to do. Other considerations After the failure of introducing the Blocking Kaizen harvester, we looked for other alternatives for storing queries. We came across multilevel queues, persistent disk queues and priority queues. Multilevel queues sounded like a good idea at first where we would have multiple queues for storing queries. But eventually, this would just boil down to how…

Continue ReadingIntroducing Priority Kaizen Harvester for loklak server

Fetching URL for Embedded Twitter Videos in loklak server

The primary web service that loklak scrapes is Twitter. Being a news and social networking service, Twitter allows its users to post videos directly to Twitter and they convey more thoughts than what text can. But for an automated scraper, getting the links is not a simple task. Let us see that what were the problems we faced with videos and how we solved them in the loklak server project. Previous setup and embedded videos In the previous version of loklak server, the TwitterScraper searched for videos in 2 ways - Youtube links HTML5 video links To fetch the video URL from HTML5 video, following snippet was used - if ((p = input.indexOf("<source video-src")) >= 0 && input.indexOf("type=\"video/") > p) {    String video_url = new prop(input, p, "video-src").value;    videos.add    continue; } Here, input is the current line from raw HTML that is being processed and prop is a class defined in loklak that is useful in parsing HTML attributes. So in this way, the HTML5 videos were extracted. The Problem - Embedded videos Though the previous setup had no issues, it was useless as Twitter embeds the videos in an iFrame and therefore, can’t be fetched using simple HTML5 tag extraction. If we take the following Tweet for example, the requested HTML from the search page contains video in following format - <src="https://twitter.com/i/videos/tweet/881946694413422593?embed_source=clientlib&player_id=0&rpc_init=1" allowfullscreen="" id="player_tweet_881946694413422593" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;"> So we needed to come up with a better technique to get those videos. Parsing video URL from iFrame The <div> which contains video is marked with AdaptiveMedia-videoContainer class. So if a Tweet has an iFrame containing video, it will also have the mentioned class. Also, the source of iFrame is of the form https://twitter.com/i/videos/tweet/{Tweet-ID}. So now we can programmatically go to any Tweet’s video and parse it to get results. Extracting video URL from iFrame source Now that we have the source of iFrame, we can easily get the video source using the following flow - public final static Pattern videoURL = Pattern.compile("video_url\\\":\\\"(.*?)\\\""); private static String[] fetchTwitterIframeVideos(String iframeURL) {    // Read fron iframeURL line by line into BufferReader br    while ((line = br.readLine()) != null ) {        int index;        if ((index = line.indexOf("data-config=")) >= 0) {            String jsonEscHTML = (new prop(line, index, "data-config")).value;            String jsonUnescHTML = HtmlEscape.unescapeHtml(jsonEscHTML);            Matcher m = videoURL.matcher(jsonUnescHTML);            if (!m.find()) {                return new String[]{};            }            String url = m.group(1);            url = url.replace("\\/", "/");  // Clean URL            /*             * Play with url and return results             */        }    } } MP4 and M3U8 URLs If we encounter mp4 URLs, we’re fine as it is the direct link to video. But if we encounter m3u8 URL, we need to process it further before we can actually get to the videos. For Twitter, the hosted m3u8 videos contain link to further m3u8 videos which are of different resolution. These m3u8 videos again contain link to various .ts files that contain actual video in parts of 3 seconds length each to support better streaming experience on…

Continue ReadingFetching URL for Embedded Twitter Videos in loklak server

How SUSI WebChat Implements RSS Action Type

SUSI.AI now has a new action type called RSS. As the name suggests, SUSI is now capable of searching the internet to answer user queries. This web search can be performed either on the client side or the server side. When the web search is to be performed on the client side, it is denoted by websearch action type. When the web search is performed by the server itself, it is denoted by rss action type. The server searches the internet and using RSS feeds, returns an array of objects containing : Title Description Link Count Each object is displayed as a result tile and all the results are rendered as swipeable tiles. Lets visit SUSI WebChat and try it out. Query : Google Response: API response SUSI WebChat uses the same code abstraction to render websearch and rss results as both are results of websearch, only difference being where the search is being performed i.e client side or server side. How does the client know that it is a rss action type response? "actions": [ { "type": "answer", "expression": "I found this on the web:" }, { "type": "rss", "title": "title", "description": "description", "link": "link", "count": 3 } ], The actions attribute in the JSON API response has information about the action type and the keys to be parsed for title, link and description. The type attribute tells the action type is rss. The title attribute tells that title for each result is under the key - title for each object in answers[0].data. Similarly keys to be parsed for description and link are description and link respectively. The count attribute tells the client how many results to display. We then loop through the objects in answers,data[0] and from each object we extract title, description and link. let rssKeys = Object.assign({}, data.answers[0].actions[index]); delete rssKeys.type; let count = -1; if(rssKeys.hasOwnProperty('count')){ count = rssKeys.count; delete rssKeys.count; } let rssTiles = getRSSTiles(rssKeys,data.answers[0].data,count); We use the count attribute and the length of answers[0].data to fix the number of results to be displayed. // Fetch RSS data export function getRSSTiles(rssKeys,rssData,count){ let parseKeys = Object.keys(rssKeys); let rssTiles = []; let tilesLimit = rssData.length; if(count > -1){ tilesLimit = Math.min(count,rssData.length); } for(var i=0; i<tilesLimit; i++){ let respData = rssData[i]; let tileData = {}; parseKeys.forEach((rssKey,j)=>{ tileData[rssKey] = respData[rssKeys[rssKey]]; }); rssTiles.push(tileData); } return rssTiles; } We now have our list of objects with the information parsed from the response.We then pass this list to our renderTiles function where each object in the rssTiles array returned from getRSSTiles function is converted into a Paper tile with the title and description and the entire tile is hyperlinked to the given link using Material UI Paper Component and few CSS attributes. // Draw Tiles for Websearch RSS data export function drawTiles(tilesData){ let resultTiles = tilesData.map((tile,i) => { return( <div key={i}> <MuiThemeProvider> <Paper zDepth={0} className='tile'> <a rel='noopener noreferrer' href={tile.link} target='_blank' className='tile-anchor'> {tile.icon && (<div className='tile-img-container'> <img src={tile.icon} className='tile-img' alt=''/> </div> )} <div className='tile-text'> <p className='tile-title'> <strong> {processText(tile.title,'websearch-rss')} </strong> </p> {processText(tile.description,'websearch-rss')} </div> </a> </Paper>…

Continue ReadingHow SUSI WebChat Implements RSS Action Type

Landing Page for Phimpme Android

Landing page for any app is very important for its distribution. Its provide all the relevant informations for the app, its download/ source link and screenshot of the app for preview of its view and features. As our Phimpme app is now reached to a milestone, so we decided to bring out a landing for it. Landing page is a simple static website which gives relevant informations and their links on a page. To develop a landing page, we can use multiple frameworks available for it. For example using Bootstrap, basic pages using html and css. As GitHub provides a free hosting service such as Github pages. I decided to work on jekyll which is easy to customize and hosted with GitHub pages. How I did in Phimpme Search for Open Source theme There are various open source themes present for jekyll, mainly you will get for blogs. I got this awesome app landing page. It fulfils our requirements of showing a screenshot, brief description and links. Create separate branch for Landing page The GitHub pages works from a separate branch. So I firstly created a orphan branch in main Phimpme Repository. And Clear the working directory. Orphan branches are those branch which do not have any commit history. It is highly required that branch should not have any commit history, because that will irrelevant for gh-pages branch. git checkout --orphan gh-pages git rm --cached -r . Test on Fork repo Now rebase your branch with the gh-pages branch created on the main repository. Add the complete jekyll code here. To reflect changes on github.io page. You need to enable that in settings. Enable gh-pages from settings Go to the Settings of your repo Scroll down to gh-pages section Here things are clear, as we need to select the source branch from where the gh-pages is hosted. We can directly choose some open source themes built over jekyll. Also there is a option to add custom domain, such phimp.me in our case. This all I’m writing as per the Developer perspective, where the developer have limited access to the repository and can’t access the settings of main repo. In that case push your code to by selecting the gh-pages base branch. Problems I faced The usual problem any Developer here faces is creating a orphan branch in main repo. This required removing all the files as well. Also to face less problem I recommend using some other editor such as Sublime Text, Atom etc. Or any other IDE other than Android Studio. Because in Android Studio after changing branch, it sync and rebuild again which actually takes lots of time. Resources GitHub Pages: https://pages.github.com/ GitHub Pages guide: https://guides.github.com/features/pages/ Create project pages using command line (Official): https://help.github.com/articles/creating-project-pages-using-the-command-line/ Adding a custom domain: https://help.github.com/articles/adding-or-removing-a-custom-domain-for-your-github-pages-site/  

Continue ReadingLanding Page for Phimpme Android

Documenting Open Event API Using API-Blueprint

FOSSASIA's Open Event Server API documentation is done using an api-blueprint. The API Blueprint language is a format used to describe API in an API blueprint file, where a blueprint file (or a set of files) is such that describes an API using the API Blueprint language. To follow up with the blueprint, an apiary editor is used. This editor is responsible for rendering the API blueprint and printing the result in user readable API documented format. We create the API blueprint manually. Using API Blueprint:- We create the API blueprint by first adding the name and metadata for the API we aim to design. This step looks like this :- FORMAT: V1 HOST: https://api.eventyay.com # Open Event API Server The Open Event API Server # Group Authentication The API uses JWT Authentication to authenticate users to the server. For authentication, you need to be a registered user. Once you have registered yourself as an user, you can send a request to get the access_token.This access_token you need to then use in Authorization header while sending a request in the following manner: `Authorization: JWT <access_token>` API blueprint starts with the metadata, here FORMAT and HOST are defined metadata. FORMAT keyword specifies the version of API Blueprint . HOST defines the host for the API. The heading starts with # and the first heading is regarded as the name of the API. NOTE - Also all the heading starts with one or more # symbol. Each symbol indicates the level of the heading. One # symbol followed by heading serves as the top level i.e. one # = Top Level. Similarly for  ## = second level and so on. This is in compliance with normal markdown format.         Following the heading section comes the description of the API. Further, headings are used to break up the description section. Resource Groups: -----------------------------     By using group keyword at the starting of a heading , we create a group of related resources. Just like in below screenshot we have created a Group Users. # Group Users For using the API you need(mostly) to register as an user. Registering gives you access to all non admin API endpoints. After registration, you need to create your JWT access token to send requests to the API endpoints. | Parameter | Description | Type | Required | |:----------|-------------|------|----------| | `name` | Name of the user | string | - | | `password` | Password of the user | string | **yes** | | `email` | Email of the user | string | **yes** |   Resources: ------------------     In the Group Users we have created a resource Users Collection. The heading specifies the URI used to access the resource inside of the square brackets after the heading. We have used here parameters for the resource URI which takes us into how to add parameters to the URI. Below code shows us how to add parameters to the resource URI. ## Users Collection…

Continue ReadingDocumenting Open Event API Using API-Blueprint