Gregory's Blog

Pressure cooked ‘KFC’ style chicken with the Magfesa star pressure cookers.

Pressure cooked 'KFC' style chicken with the Magfesa star pressure cookers.

There is absolutely nothing better than 'KFC' style pressure cooked chicken made at home. However, you can only do this with a very limited number of pressure cookers, namely a Magfesa star pressure cooker1, with an extra metal arm that is wrapped around the lid. You can also do this at home using older chicken bucket cookers, but the safety features on the older style pressure cookers aren't as good. You can't do this with any other pressure cooker- certainly not your insta-pot! It will blow up or just melt. Magfesa does not advertise that you can pressure cook using oil due to legal liability- but it is made like the old chicken buckets, and folks use these specific pressure cookers when they use oil. I have cooked this recipe many times at home using a 16 quart Magfesa cooker, but I am super diligent and carefully follow this method.

Add the following in a glass bowl:

  • ½ teaspoon Cayenne pepper. Black pepper, salt.
  • Fill up to the top with buttermilk.
  • Optional: 1 beaten egg.
  • Let chicken sit in buttermilk in the refrigerator for at least 30 minutes. I try to leave in in the fridge for at least two hours. You can also leave it overnight.
  • Take chicken out of fridge for 30 minutes.
  • Create the breading. My typical ingredients include:

    • 2 Cups of flour.
    • 1/3 cup of parmesan cheese.
    • 1 teaspoon Cajun spice mix.
    • 1 teaspoon basil.
    • 1 teaspoon rosemary.
    • 1 teaspoon thyme.
    • ½ teaspoon Cayenne pepper.
    • ½ teaspoon Greek seasoning.
    • ½ teaspoon paprika.
    • ½ teaspoon celery salt.
    • ½ teaspoon ground ginger.
    • ½ teaspoon black pepper.
    • ½ teaspoon salt.

  • Mix thoroughly.
  • Take the chicken out of the buttermilk mixture. Shake the chicken gently in order to drain off the buttermilk for 30 seconds or so. Once drained off, dredge the chicken through the flour spice mix. Use tongs while dipping chicken into mixture.
  • Put aside on lined baking sheet.
  • Wait 30 minutes, dredge again. This time it does not use as much flour. You're only trying to cover portions that were not covered in the first dredge.
  • Wait for 30 minutes to allow chicken to warm up to room temperature. This also allows the flour mixture to bond with the chicken.
  • Dredge again and lightly season the chicken with any extra herbs that you want to put in. Don't over-season.
  • Inspect the main seal and the spinning pressure release by blowing into it and seeing if air comes out. Do not continue if the seal or release valve is not working.
  • In pressure cooker, heat peanut oil up to 350 degrees with the top off. Use a long thermometer to gage temperature. You must use peanut oil, or a specialty oil mixes that are sold to deep fry turkeys with.
  • Other oils won't hold up with the high temperatures, and they may catch fire as the smoke point is too low.
  • Once the peanut oil reaches 350 degrees, use long tongs and carefully drop chicken into the oil. Work in batches, even with a large pressure cooker, I only put in 4-6 pieces of chicken at a time. It is also advisable to wear thick insulated gloves that you would wear when using a BBQ. Be careful of splattering.
  • Cover the pressure cooker and tighten. Wait a minute or two to allow the pressure to build. Do not leave the area once you have applied heat to the pressure cooker.
  • Once pressure builds up and the pressure release top starts spinning, immediately turn down the heat on the burner down a little more than 2/3rds without actually turning the stove off. I turn my electric stove down to 4 (high is set at 15), and set the timer.

  • Set timer for:
    • Legs: 10 minutes.
    • Thighs: 12 minutes.
    • Breast: 15 minutes.

  • Watch the pressure cooker carefully- if the release top starts spinning like crazy, turn the burner down further. If the emergency pressure release is popped (the 2nd safety feature, turn the stove off and move the pot off of the burner.
  • After the timer goes off, release the pressure manually and carefully use tongs to pull the chicken out. I do not put the pressure cooker under water to quick release the pressure. Play it safe- water and oil do not mix.
  • Make sure that the pressure is released before opening the lid, otherwise, you may have oil come up the pot, make a mess, and perhaps get burned.

Helpful tips: for chicken breasts and thighs, you can also gently precook or smoke the meat halfway done prior to soaking the chicken in the butter milk. This allows you to shorten the time by a few minutes and not over-burn the skin.

Happy (and safe) eating!

Further reading:
Cookistry: Pressure fried chicken
Serious Eats: Gadgets: Magefesa Star Pressure Cooker

1Note: I am in no way affiliated with Magfesa, and don't derive any income from this post. I just like deep fried chicken and this is the most economical way to make this at home!

This entry was posted on October 14, 2019 at 8:15 PM and has received 51 views.

Building your own Disqus Recent Comments Widget

Disqus's commenting system is one of the most popular free blog plugin's in the world right now. It allows blog users to log in using various social media services such as Facebook and Twitter, and offers a bevy of tools and comment moderation features. Most of the popular open source blogs (now including Galaxie Blog) have optional built in Disqus integration. However, what if you as the developer want to implement Disqus into your own custom software or blog? This article will show you a way to use the Disqus API key to build your own custom recent comments Disqus widget.

Do you really need your own custom Disqus Recent Comments Widget?

A recent comments widget is a tool that allows blog owners to show the most recent comments on a page. If you're just using Disqus on a static site that does not contain all of the blog entries, you might not need to roll your own custom recent comment widget. And, even if you do have a page that contains all of the blog entries, you may not need a custom widget- Disqus already provides one. To incorporate it, all that you need to do is replace the 'gregorys-blog' string with your own Disqus Blog Identifier (also known as the blog short name) like so:

view plain about
1<script type="text/javascript" src="https://gregorys-blog.disqus.com/recent_comments_widget.js?num_items=10&hide_avatars=0&avatar_size=40&excerpt_length=100"></script>
This is a basic widget, and it contains nearly everything that you may need. My code falls back to this approach in Galaxie Blog when the blog owner does not paste in his own API Key. However, it is not flexible. It is what you see is what you get, and I wanted to blend the recent comment widget with Galaxie Blogs themes, and needed other things, such as having to use the Disqus API to have my own statistical reporting. I'm a stickler for design- I personally determined from the outset that I need roll my own Disqus recent comments widget, and I'll share my approach...

Building your own Disqus Recent Comments Widget

  1. First, you will need to obtain a Disqus Blog Identifier (aka Blog Short Name) and a Disqus API Key. If you don't already have these keys, the following articles should help you in getting these:
  2. The code below is the style sheets that I developed for Galaxie Blogs recent comments. There is nothing interesting to note here but I am sharing to give you a starting point:

view plain about
1<!--- Styles for disqus --->
2<style>
3    .userProfile {
4        margin: 15px 0;    
5        list-style-type: none;    
6        clear: both;
7    }
8
9    img.disqusAvatar {
10        width: 64px;
11        height: 64px;
12        float: left;
13        position: relative;
14        z-index: 99;
15        border: 0px;
16        margin: 0px;
17        /* The padding needs to be uniform, otherwise the avatar circle will be elongated */
18        padding: <cfoutput>#avatarPadding#</cfoutput>;
19        -moz-border-radius: 50%;
20        -webkit-border-radius: 50%;
21        -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
22        -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
23        box-shadow: 0 1px 2px rgba(0,0,0,0.2);
24        overflow: hidden;
25    }
26
27    #disqusCommentDiv a {
28        overflow: hidden; /* Prevent wrapping */
29    }
30
31    #disqusCommentDiv p {
32        display: inline; /* Prevent wrapping */
33    }
34
35    #disqusCommentPanel a {
36        overflow: hidden; /* Prevent wrapping */
37    }
38
39    #disqusCommentPanel p {
40        display: inline; /* Prevent wrapping */
41    }
42
43    .comment-avatar img {
44        width: 100%;
45        height: 100%;
46    }
47</style>

  1. The real magic happens in the javascript below. I'll try to walk you through some of the more interesting tidbits
    1. The getRecentDisqusComments function makes a call to the Disqus API invoking the listsPosts method
    2. Additionally, the related=thread argument is appended to the URL string. This argument allows us to get the URL and Title of the post. Without this argument, we would need to make another call the threads list method, which is frankly a nightmare1.
    3. We are passing our Disqus keys in the Ajax post
    4. The getDisqusCommentsResponse callback method retrieves the data, and writes out our custom HTML. Here, I am using my own custom class definitions to make the widget blend in with my own themes.
    5. The isOdd method assists creating alternate the colors of each row.
    6. The timeSince method is used to append a string to tell the viewer when the comment was made (ie '20 seconds ago').
    7. Finally, the truncateString method is used to truncate the comment string.

view plain about
1function getRecentDisqusComments(){
2
3    // Submit form via AJAX.
4    $.ajax(
5        {
6            type: "get",
7            url: "https://disqus.com/api/3.0/forums/listPosts.json?related=thread",
8            data: {
9                // Passing my own keys.
10                api_key: "<cfoutput>#application.disqusApiKey#</cfoutput>",
11                forum: "<cfoutput>#application.disqusBlogIdentifier#</cfoutput>",
12
13                limit: "<cfoutput>#numComments#</cfoutput>"
14            },
15            // jsponp is supported as well.
16            dataType: "json",
17            cache: false,
18            success: function(data) {
19                setTimeout(function () {
20                    // Callback function
21                    getDisqusCommentsResponse(data);
22                // The timeout ensures that the data will be available to the callback function.
23                }, 250);
24            }
25        }
26    );
27}//..function getRecentDisqusComments(){
28
29function getDisqusCommentsResponse(data){
30    var html = "";
31    // Loop through the json structure.
32    for (var i = 0, len = data.response.length; i < len; i++) {
33        // Isolate our post (or entry).
34        var post = data.response[i];
35        // Set a current row value from our index. I need a whole number to determine the alternating row color. I could just use [i]+1, but I am setting this for readability.
36        var row = parseInt([i]);
37        // Get the data for the post.
38        var authorName = post.author.name;
39        var authorProfileUrl = post.author.profileUrl;
40        var authorAvatarUrl = post.author.avatar.cache;
41        // We need to strip the HTML out of the comment. It has links that are not useful and will take up our space.
42        var comment = stripHtml(post.message);
43        var commentPromoted = post.isHighlighted;
44        var approved = post.isApproved;
45        // Get the timestamp and convert it into a proper js date object.
46        var created = new Date(post.createdAt);
47        // Find the link to the actual article. Note: for this to work, you must have related=thread appended to the ajax link (ie https://disqus.com/api/3.0/forums/listPosts.json?related=thread).
48        var pageLink = post.thread.link;
49        var pageTitle = post.thread.title;
50
51        // Create the HTML. We will try to keep this nearly identical to the recent comment widget, but put in our own kendo classes here.
52        // Crete the table on the first row.
53        if (row == 0){
54            html += '<table id="disqusComment" align="center" class="k-content fixedPodTableWithWrap" width="100%" cellpadding="0" cellspacing="0">';
55        }
56        // Create the row and alternate the k-content and k-alt class.
57        if (isOdd(row)){
58            html += '<tr class="k-alt" height="50px;">';
59        } else {
60            html += '<tr class="k-content" height="50px;">';
61        }
62        // After the first iteration, create a row with a border. Javascript arrays (which is our 'row') start at 0.
63        if (row == 0){
64            html += '<td align="left" valign="top" class="userProfile">';
65        } else {
66            html += '<td align="left" valign="top" class="border userProfile">';
67        }
68        // Wrap the avatar with the authors profile link
69        html += '<br/><a href="' + authorProfileUrl + '" aria-label="Profile for ' + authorName + '" rel="nofollow noopener">' + authorName;
70        // Place the avatar into the cell and close the anchor link.
71        html += '<img class="disqusAvatar" src="' + authorAvatarUrl + '" aria-label="Profile for ' + authorName + '"></a><br/>';
72        // Add the comment. The comment is already wrapped with a paragraph tag.
73        html += truncateString(comment, <cfoutput>#lenComment#</cfoutput>) + '<br/>';
74        // Create the HTML to insert into the page title.
75        html += '<a href="' + pageLink + '" aria-label="' + pageLink + '">' + pageTitle + '</a> - ';
76        // Add the timestamp to quickly identify how recent the post is.
77        html += timeSince(new Date(created)) + ' ago<br/>';
78        // Close the cell and the row.
79        html += '</td></tr>';
80        // Close the table on the last row
81        if (row == <cfoutput>#round(numComments-1)#</cfoutput>){
82            html += '</table>'
83        }
84        // Append the html to the page.
85        $(document).ready(function() {
86            $("#recentCommentsDiv").html(html);
87            $("#recentCommentsPanel").html(html);
88        });
89
90    }//..for (var i = 0, len = data.response.length; i < len; i++) {
91
92}
93
94// Helper function to determine if the number is even or odd. This is used to create alternating row colors.
95function isOdd(num) {
96    return num % 2;
97}
98
99function stripHtml(html){
100    html.replace(/<[^>]*>
?/gm, '');
101    return html;
102}
103
104// Function to write out the time since the post.
105// Source: https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site    
106function timeSince(date) {
107 var seconds = Math.floor((new Date() - date) / 1000);
108 var interval = Math.floor(seconds / 31536000);
109
110 if (interval >
1) {
111    return interval + " years";
112 }
113 interval = Math.floor(seconds / 2592000);
114 if (interval >
1) {
115    return interval + " months";
116 }
117 interval = Math.floor(seconds / 86400);
118 if (interval > 1) {
119    return interval + " days";
120 }
121 interval = Math.floor(seconds / 3600);
122 if (interval > 1) {
123    return interval + " hours";
124 }
125 interval = Math.floor(seconds / 60);
126 //alert(interval + ' minutes date: ' + date);
127 if (interval > 1) {
128    return interval + " minutes";
129 }
130 return Math.floor(seconds) + " seconds";
131}
132
133truncateString = function(str, length, ending) {
134    if (length == null) {
135        length = 100;
136    }
137    if (ending == null) {
138        ending = '...';
139    }
140    if (str.length > length) {
141        return str.substring(0, length - ending.length) + ending;
142    } else {
143        return str;
144    }
145};
146
147// Call the method to populate the recent comments.
148getRecentDisqusComments();

If you have any questions, don't hesitate to ask.

Happy commenting!

Further Reading: 1Raymond Camden has an excellent article at https://www.raymondcamden.com/2014/03/21/Example-of-a-JavaScript-Disqus-Recent-Comment-Widget. I wished that I had read this earlier before going down my own rabbit hole. To get the related post, I initially tried to call the thread list method (at https://disqus.com/api/3.0/threads/list.json) within a nested ajax post. My initial code was just... ugly. Finally, I stumbled upon this article and found out that I could simply use the related=thread argument to attach the comment to a thread.

This entry was posted on October 7, 2019 at 9:06 PM and has received 101 views.

Adding multiple Disqus comments on one page

While incorporating comments into my main blog page, I found out that Disqus does not provide a native way to place multiple comments on a single page. The Disqus commenting system includes an embedded javascript at the end of an article. The javascript writes out the commenting interface using global variables and it can't be included twice. This poses a problem as my main blog page contains all of my blog posts, and I wanted the readers to be able to comment without having to go to each individual entry page. After research, I figured out way. I'll share my approach and give the reader other resources so they can do the same.

Background

While researching, I found a promising lead... Most of the folks that have skinned this cat referred to an article written by mystrdat that is now long since dead. I dug it up using the wayback machine at https://web.archive.org/web/20170606070513/http://mystrd.at/articles/multiple-disqus-threads-on-one-page/. It is an excellent article, and if you're trying to do the same thing, it is worth a read.

There were other helpful resources that I found. Shawn Zhou provides a list of articles that solved this issue. Shawn uses iframes to encapsulate the Disqus comments. Tsachi Shlidor shared his approach using inline comments. His demonstration and code is on github at http://tsi.github.io/inlineDisqussions/.

Since I already built my own commenting system using the open sourced Kendo Core UI window widgets, I chose a different approach. I am encapsulating Disqus logic into various Kendo windows. You can use the same approach that I used with a different windowing library, such as jQuery UI.

Using multiple Disqus comments using a Kendo window widget

  1. First, I took the Disqus universalcode script and saved it as a new ColdFusion template. Note that the this.page.url and this.page.identifier are dynamic variables. These will be passed to the window via the URL.

view plain about
1<!--- Note: the disqus_shortname, URL and identifier are passed to this page via the URL. --->
2<div id="disqus_thread"></div>
3<script type="text/javascript">
4    /**
5    * RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
6    * LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#chr(35)#configuration-variables*/

7    
8    var disqus_config = function () {
9    var disqus_shortname = '<cfoutput>#URL.alias#</cfoutput>';
10    this.page.url = '<cfoutput>#URL.url#</cfoutput>'; // Replace PAGE_URL with your page's canonical URL variable
11    this.page.identifier = '<cfoutput>#URL.Id#</cfoutput>'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
12    };
13    
14    (function() { // DON'T EDIT BELOW THIS LINE */
15        var d = document, s = d.createElement('script');
16        s.src = 'https://gregorys-blog.disqus.com/embed.js';
17        s.setAttribute('data-timestamp', +new Date());
18        (d.head || d.body).appendChild(s);
19    })();
20</script>

  1. Second, I created the scripts to create a new Kendo window. The only thing of interest in the code below is that I am passing the URL and Identifier variables that the universal code script needs (this.page.url and this.page.identifier in the code above):

view plain about
1// Disqus comment window ---------------------------------------------------------------------------------------------------------------------------------
2function createDisqusWindow(Id, alias, url) {
3
4    // Remove the window if it already exists
5    if ($("#disqusWindow").length >
0) {
6        $("#disqusWindow").parent().remove();
7    }
8
9
10    // Typically we would use a div outside of the script to attach the window to, however, since this is inside of a function call, we are going to dynamically create a div via the append js method. If we were to use a div outside of this script, lets say underneath the 'mainBlog' container, it would cause weird problems, such as the page disappearing behind the window.
11    $(document.body).append('<div id="disqusWindow"></div>');
12    $('#disqusWindow').kendoWindow({
13        title: "Comments",
14        actions: ["Minimize", "Refresh", "Close"],
15        modal: false,
16        resizable: true,
17        draggable: true,
18        // For desktop, we are subtracting 5% off of the content width setting found near the top of this template.
19        width: (getContentWidthPercentAsInt()-5 + '%'),
20        height: "60%",
21        iframe: false, // Don't use iframes unless it is content derived outside of your own site.
22        content: "/blog/disqus.cfm?id=" + Id + '&alias=' + alias + '&url=' + url,// Make sure to create an absolute path here. I had problems with a cached index.cfm page being inserted into the Kendo window probably due to the blogCfc caching logic.
23
24        close: function() {
25            $('#disqusWindow').kendoWindow('destroy');
26        }
27
28    }).data('kendoWindow').center();
29}//..function createDisqusWindow(Id, alias, url) {
30
31// The mobile app has a dedicated button to close the window as the x at the top of the window is small and hard to see
32function closeDisqusWindow(){
33    $("#disqusWindow").kendoWindow();
34    var disqusWindow = $("#disqusWindow").data("kendoWindow");
35    setTimeout(function() {
36     disqusWindow.destroy();
37    }, 500);
38}

  1. Then, on the web page itself, I am showing the following button that calls the createDisqusWindow function above. I am adding this button for every single blog entry on the page. In the button, I am adding the entry ID as the first argument (the this.page.identifier), the 2nd argument, the entries 'alias' (disqus_shortname), and the entry URL is passed to the this.page.url.

view plain about
1<button id="disqusCommentButton" class="k-button" style="width:125px; font-size:0.70em;" onClick="createDisqusWindow('6C04DC8C-FF58-C02F-8C38E2BEEBCA282B', 'Incorporate-Disqus-into-Galaxy-Blog--Part-3', 'https://gregoryalexander.com/blog/index.cfm/2019/10/6/Incorporate-Disqus-into-Galaxy-Blog--Part-3')">
2    <i class="fas fa-comments" style="alignment-baseline:middle;"></i>&nbsp;&nbsp;Comment
3</button>

  1. To display the comment count, I am placing the disqus-comment-count with the URL of the entry. Note: if you want, you can replace the span tags with an anchor tag ('a href') and include an onClick event to open up the comments window.

view plain about
1<span class="disqus-comment-count" data-disqus-url="https://gregoryalexander.com/blog/index.cfm/2019/10/6/Incorporate-Disqus-into-Galaxy-Blog--Part-3"></span>

  1. Finally, at the very bottom of the index.cfm page, I am adding the disqus comment count script:

view plain about
1<script id="dsq-count-scr" type="deferjs" src="//gregorys-blog.disqus.com/count.js" async></script>

For a demonstration, go to https://gregoryalexander.com/blog/index.cfm, click on a comment link, and make a comment or at least say hi!

Happy coding!

Gregory

This entry was posted on October 7, 2019 at 2:10 PM and has received 77 views.

Incorporate Disqus into Galaxy Blog - Part 3


Use your Disqus Blog Identifier and your optional API key to incorporate Disqus into your own Galaxie Blog.

  1. Once you have your own Disqus Blog Identifier, you can immediately incorporate Disqus using Galaxie Blog. In the current version of Galaxie Blog (version 1.45 or above), open the index.cfm template found in the root directory. Search for the 'application.includeDisqus' string using your IDE, and set the includeDisqus variable to true. It should be around line 26, a code example is provided below:

view plain about
1<!--- Determine whether to include the disqus commenting system. If you set this to true, you must also set the optional disqus settings that are right below. --->
2<cfset application.includeDisqus = true><!--- true or false. --->

  1. Now, search for "application.disqusBlogIdentifier". It should be down a few lines. Copy and paste your Disqus Blog Identifier, also known as the Disqus Short Name, into the disqusBlogIdentifier variable.
  2. Next, if you have a Disqus API Key, copy and paste that into the application.disqusApiKey variable. For now, the other Disqus settings below should be left alone.
  3. In an upcoming version, I'll add Disqus integration to the administrative interface.

view plain about
1<cfset application.disqusBlogIdentifier = "YourFreeDisqusBlogIdentifier"><!--- Required if you're using Disqus. --->
2<cfset application.disqusApiKey = "YourFreeDisqusAPIKey"><!--- Optional --->

That's it! Upload the file, and your Disqus commenting system should be in place.

Happy Blogging!

Gregory

This entry was posted on October 6, 2019 at 7:13 PM and has received 74 views.

Obtaining a Disqus API Key - Part 2

After you register your Disqus account, you should also consider signing up for a free Disqus API Key. A Disqus API Key allows you to build your own widgets, such as a recent comments interface. For Galaxie Blog owners, the optional API Key allows Galaxie Blog to display my own custom recent comments interface that blends in with the Galaxie Blog themes. It also allows Galaxie Blog to have an accurate comment count in the administrative interface. The API key is free, and the free version generously allows for 10,000 calls per hour at the time of writing. The limit is sufficient on immensely popular blogs, such as Raymond Camdens blog. The free API key should suffice.

  1. Don't look for the API key after registering your site with Disqus. It is not available using the default Disqus interface. You will have to go to the Disqus API page.
  2. Navigate to https://disqus.com/api/applications/ and click on Applications
  3. Enter your site information and register your application
  4. On the next page, leave the default settings as they are. You don't need to add or change anything, just click Save changes


  1. The next screen is a little confusing. At the time of the writing, it seems as you have just refreshed the page. Here, just click on the Details link at the top of the page. I am attaching a screen shot.
  2. Your new Disqus API Key is found underneath the OAuth settings on the Details screen.
  3. If you are here just to obtain your Disqus Blog Identifier (aka short name) and API key for Galaxie Blog, continue to the next page. If you're a developer looking into incorporating Disqus into your own site, you may want to take a look at the Common Libraries page.


Next up... how to use the Disqus Blog Identifier and API Key to incorporate Disqus in Galaxie Blog.

This entry was posted on October 6, 2019 at 5:13 PM and has received 103 views.

Register your site with Disqus - Part 1

In this series of Disqus articles, you will learn how to incorporate Disqus into your own site, or incorporate it into Galaxie Blog. Galaxie Blog requires two keys- the Disqus Blog Identifier (or Short Name), and optionally, a Disqus API Key. I will try to write this for Galaxie Blog users of course, but also for others who may want to follow along the same footsteps to incorporate Disqus into their own blog. I will walk you through the steps to register with Disqus, and share my approach and code that I used here. I will also show you how to use multiple Disqus comments on one page, how to get the comment count, and walk you through the steps to build your own recent comments widget.

To incorporate the Disqus comment system into your own blog, you first need to create a Disqus account to obtain your Disqus Blog Identifier, otherwise known as your blog's short name. You should also create a free developer account in order to acquire a Disqus API key. I will briefly walk you through the required steps to obtain both keys. If you already have a Disqus blog identifier and API key, you should skip this article and read part 3.

Register your site and obtain your Disqus Blog Identifier

  1. First, sign up for a free Disqus account at www.disqus.com
  2. Click on the get started button
  3. Enter your name, email, and create a password. You will need to verify your email with Disqus before you continue.
  4. Once you're done creating your profile, click on I want to install Disqus on my site.


  1. Register your site by including the name of your site, and choose an appropriate category.
  2. Prior to clicking on the Create Site button, you'll notice the short name of your site. I highlighted the short name with a circle. If you didn't notice this before registering, don't worry- you will be able to look it up later.
  3. Click on Create site.

  1. For a personal blog, I recommend selecting the Basic plan. The basic plan does have a Disqus label at the bottom of the comments interface, but it is free. You're welcome to choose a paid plan if you want, but it is not necessary.
  2. You don't need to do anything on the Select Platform interface. I have integrated Disqus into Galaxie Blog. We need to move on to the configuration settings.
  3. In the configuration settings, enter in the website name, url, category and description. You don't need to enter pages for your own policies right now, you can come back to this later.
  4. Click on Complete setup button



  1. On the next Setup Complete page, scroll to the bottom of the page and click on the Configure your sites community settings link.
  2. Take note of your blogs Short Name in the 2nd setting. Copy this string. You will need it later to paste into Galaxie Blogs disqusBlogIdentifier setting.
  3. Make sure that the color scheme is set to automatic. This is needed to have Disqus adjust the comment interface with Galaxie Blog's multiple themes.
  4. Click on Save button



That's it, your set! In part two, we'll go over the steps needed to get your own Disqus API key.

This entry was posted on October 5, 2019 at 8:52 PM and has received 126 views.

Disqus has been incorporated into Galaxie Blog

I released the next version of Galaxie Blog that allows the Blog owner to integrate Disqus. Disqus is one of the most popular blog commenting systems, and it allows for social media integration, user profiles, and sophisticated spam and moderation tools. Galaxie Blog allows you to incorporate Disqus either using a simple Disqus Blog identifier, or using both an identifier and a Disqus API Key. Both of Disqus keys are easily obtained, and both are free. Here are the settings in Galaxie Blog that will allow you to easily incorporate Disqus into your own Galaxie Blog:

view plain about
1<!--- Determine whether to include the disqus commenting system. If you set this to true, you must also set the optional disqus settings that are right below. --->
2<cfset application.includeDisqus = true><!--- true or false. --->
3<cfset application.disqusBlogIdentifier = "YourFreeDisqusBlogIdentifier"><!--- Required if you're using Disqus. --->
4<cfset application.disqusApiKey = "YourFreeDisqusAPIKey"><!--- Optional --->

The API key requires the user to sign into a Disqus site for developers, but having one allows Galaxie Blog to display the recent comments that blend into the Galaxie Blog's themes.

Disqus is optional though. You can still use the default Galaxie Blog commenting system that has moderation tools, spam control with captcha, etc. However, the default Galaxie Blog commenting system does not allow for social media sign-on. In the future, I hope to develop a robust commenting system that matches the core functionality with Disqus, but this will take time.

I will write several technical entries in the next couple of weeks in order to share my approach.

This entry was posted on October 5, 2019 at 1:02 PM and has received 158 views.

Demonstrating the benefits of the new webp image format

The next generation webp format is one of the most important image formats to have come along in the last several years.

My first impression of webp images was 'meh'. I read articles on the next generation webp image format. The articles claim that webp images are about 26% smaller than their png equivalents. What I read was impressive, but not just enough to delve into learning how to use them.

I only started playing around with webp to chase a better Google lighthouse score. Google knocked my 'Best Practices' score down a couple of notches, and I finally decided to investigate using them. I'm glad that I did! I did not find a 26% improvement with my own images, but a 95% improvement in size than the identical .png images that I had created. Want proof? I'll demonstrate my own results...

Please take a look at my Greensock animation introducing the next version of Galaxie Blog at https://gregoryalexander.com/blog/index.cfm/2019/9/16/Galaxie-Blog-135-Animated-Blurb. If you're using a modern browser, you should notice that this intense graphical scene renders rather quickly. On a vain note- I also hope that you find the scollmagic scene to be pretty...

The scrollmagic scene that you are looking at should deliver images in the webp format if your browser supports them. If the browser does not support webp, png's will be rendered instead. I'll go over the code later on, but right now I will compare the image sizes to show you the improvements. I'll provide the link and size of each actual image in the grid below so you can take a look yourself.

I created the original source images using Adobe Illustrator, and exported them to png's using the 'save as legacy web' option. To create the web images, I took the png images that I had created and used Irfanview to export the png as a webp. Take a look at the size reduction in the table below.

The entire payload of all of the combined webp images is 90% less than one of the actual png images! With this type of extreme size reduction we can vastly improve our loading time, or we can now use full quality images in animated sequences like this!

I am also using webp instead of jpg images. Here the improvements are not as as substantial, but I have shaved about 10-15% of the size of the jpg images.

How to get started with webp images.

Server side code

Currently, with the exception of Safari- most modern HTML5 capable browsers support webp images. To determine if a browser supports the next generation format is relatively easy. Thankfully, nearly all modern browsers will include webp support in the header if the browser supports the webp next gen image. Here is the ColdFusion script that I developed.

view plain about
1<!--- Determine if the http accept header contains webp. The getHttpRequestData().headers is a structure and we are targetting the accept element in the array. Note: nearly all modern browsers will include this if the browser supports the webp next gen image. --->
2<cfset acceptHeader = getHttpRequestData().headers["accept"]>
3<!--- Does the header accept webp? --->
4<cfif findNoCase("webp", acceptHeader) gt 0>
5    <cfset clientAcceptsWebP = true>
6<cfelse>
7    <cfset clientAcceptsWebP = false>
8</cfif>

A hybrid server side and client side approach

Most web servers support the webp image format as well. However, on web servers that are not current, you may need to add the webp mime type. Consult with your ISP or server documentation to find out how to add webp mime type on your server. Here is the function that I developed to test webp support on the server and save the result as a persistent application variable. You will have to create a small webp image and upload to your own server for this to work (see headerBodyDivider.webp below).

view plain about
1<!--- Determine if the webP mime type is set up on the server. --->
2    <cffunction name="serverSupportsWebP" access="public" returntype="boolean" output="yes">
3        <!--- Note: we need to eliminate https from the root URL if it exists. I ran into errors trying this with https (a cryptic certificate error). --->
4        <cfset thisUrl = replaceNoCase(application.rootUrl, "https", "http")>
5        <!--- The headerBodyDivider image is a tiny .webp image (around 1k). We are going to read this, and if it was found and the mime type is correct, we will assumed that the mime type is correct. Otherwise, we will determine that the server does not support the webp mime type. --->
6        <cfhttp method="get" URL="#thisUrl#/images/divider/headerBodyDivider.webp">
7            
8        <!--- Was the webp image found? --->
9        <cfif cfhttp.mimeType contains 'webp'>
10            <cfset webp = true>
11        <cfelse>
12            <cfset webp = false>
13        </cfif>
14        <!--- Return it. --->
15        <cfreturn webp>
16    </cffunction>

In my code, I either use the server side logic above to test both the server and the client for webp support, or I use a hybrid approach where I save the result of the serverSupportsWebP server side function and test for support using javascript on the client like so:

view plain about
1<script>
2        // WebP support detection. Revised a script found on stack overflow: https://stackoverflow.com/questions/5573096/detecting-webp-support. It is the quickest loading script to determine webP that I have found so far.
3        function webPImageSupport() {
4            // Detemine if the webp mime type is on the server. This is saved as a ColdFusion application variable.
5            var serverSupportsWebP = <cfoutput>#application.serverSupportsWebP#</cfoutput>;
6         var elem = document.createElement('canvas');
7            
8         if (serverSupportsWebP && !!(elem.getContext && elem.getContext('2d'))) {
9         // Is able to get WebP representation?
10         return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0;
11         }
12         // webp is not supported on older browsers such as IE.
13         return false;
14        }
15    </script>

Using either approach is valid. However, I typically use server side code to set the paths of my images, and only use the hybrid approach (using the script above) when I am manipulating the DOM with javascript.

Example server side logic to set the image extension

I personally set the default image to be png or jpg, and only change it if both the client and the server support webp:

view plain about
1<!--- Determine if the http accept header contains webp. The getHttpRequestData().headers is a structure and we are targetting the accept element in the array. Note: nearly all modern browsers will include this if the browser supports the webp next gen image. --->
2    <cfset acceptHeader = getHttpRequestData().headers["accept"]>
3    <!--- Does the header accept webp? --->
4    <cfif findNoCase("webp", acceptHeader) gt 0>
5        <cfset clientAcceptsWebP = true>
6    <cfelse>
7        <cfset clientAcceptsWebP = false>
8    </cfif>
9        
10    <!--- Logic to determine if the server has the necessary webp mime type was done in the application.cfc template. We will use the application.serverSupportsWebP variable that the mime type is installed on the server. Of course, both the client and the server need to support webp images before we can deliver them.--->
11    <cfif application.serverSupportsWebP and clientAcceptsWebP>
12        <cfset webpImageSupported = true>
13    <cfelse>
14        <cfset webpImageSupported = false>
15    </cfif>
16        
17    <cfif webpImageSupported>
18        <!--- Overwrite the headerBodyDividerImage var and change the extension to .webp --->
19        <cfset headerBodyDividerImage = replaceNoCase(headerBodyDividerImage, '.png', '.webp')>
20    </cfif>

Tips

When saving webp images, don't use the Adobe Photoshop or Illustrator plugin's. There are two of them as of today, and neither of them work well. Instead, just create your images and save them as jpg or png, and use Irfanview 64 to open and save them as a webp image. I have tried many approaches, and this method has proven to be the most reliable.

Thanks for reading, and happy coding!

Gregory

This entry was posted on September 17, 2019 at 12:31 AM and has received 257 views.

Introducing Galaxie Blog 1.35 with a new Parallax Scene


Galaxie Blog is a Next Generation Blog Platform

Galaxie Blog is the most beautiful and functional open sourced ColdFusion blog in the world.

galaxie Parallax Image 1
galaxie Parallax Image 2
galaxie Parallax Image 3
galaxie Parallax Image 4
galaxie Parallax Image 5
galaxie Parallax Image 6

Galaxie Blog is fast....

Galaxie Blog consistently performs above 80% in Google lighthouse scores...

For comparison, the industry average performance score of the top ecommerce sites is is around 22%

Galaxie Blog is Accessible...

Galaxie Blog has a perfect 100% 'Accessibility' Google Score

The industry average sites is around 60%.

Galaxie Blog has a perfect 100% 'Best Practices' Google Score

Galaxie Blog uses all of the 'Best Practices' suggested by Google.

The industry average score is about 61%

Galaxie Blog has a perfect 'Search Engine Opimization (SEO)' score.

Having a perfect SEO ensures that search engines will be able to collect and promote your content.

Galaxie Blog allows you to enforce SSL....

Blog owners can specify whether to enforce SSL. If SSL is enforced, all port 80 traffic will be a automatically redirected to an encryted port.

Galaxie Blog delivers next generation media content...

Galaxy Blog now delivers webp images if both the client and the server support the new webp format.

If webp is not supported, Galaxy Blog will fallback and deliver images using tradional web formats.

Improved Entry Image Support

Administrators can easilly add images to their entries by clicking on a button and selecting an image. Galaxie Blog will take care of the rest.

To improve performance, Galaxie Blog will only render the image once it comes into the user's viewport.

Improved Social Media Sharing

Galaxie Blog now prominently displays social media icons to share your social media at the bottom of each individual blog entry.

You can use dynamic includes within an entry using xml.

This very GSAP scene that you're looking at now is acheived using a dynamic cfinclude.

Goals for the next version...

Overhaul the original database and add 'Disqus' integration.

Galaxie Blog is still using the original BlogCfc database and it must be updated. If feasable, I will add Disqus comment integration.

 

This entry was posted on September 16, 2019 at 12:50 PM and has received 215 views.

Google Lighthouse Metrics for Galaxie Blog Version 1.35



I am finally done chasing a nearly perfect Google lighthouse score and have released Galaxie Blog version 1.35. I have a perfect score for 3 out of 4 categories, and the performance score generally falls between 70 and 90. Performance: 90%1 Accessibility: 100% Best Practices: 100%2 and SEO (Search Engine Optimization): 100%

Attaining this score was not easy- especially for a large blog site. This is major accomplishment.

I spent over a month working on all aspects of the site. The google audit checklist is exhaustive. For example, I am deferring all non essential resources until page load, lazy loading the images and media, using next generation image formats (webp)3 and networking protocols (http/2) if possible, have no errors written to the console, etc, etc.

I will write up several blog entries in the next couple of weeks to highlight some of my approaches.

1 Performance results can vary considerably.
2 Attained with the commercial Kendo license. The open source Kendo Best Practices score is at 86 due to the Kendo embedded jQuery library. According to Telerik, this should be fixed in the near future.
3 Webp images are only served when both the client and the server supports them. When webp is not supported, Galaxie Blog will fallback to traditional image protocols. I will write up an article on this in the near future.

This entry was posted on September 13, 2019 at 12:29 PM and has received 224 views.

Related Entries




Footer Logo

Your input and contributions are welcomed!

If you have an idea, BlogCfc based code, or a theme that you have built using this site that you want to share, please contribute by making a post here or share it by contacting us! This community can only thrive if we continue to work together.

Images and Photography:

Gregory Alexander either owns the copyright, or has the rights to use, all images and photographs on the site. If an image is not part of the "Galaxie Blog" open sourced distribution package, and instead is part of a personal blog post or a comment, please contact us and the author of the post or comment to obtain permission if you would like to use a personal image or photograph found on this site.

Credits:

Portions of Galaxie Blog are powered on the server side by BlogCfc, an open source blog developed by Raymond Camden. Revitalizing BlogCfc was a part of my orginal inspiration that prompted me to design this site. Some of the major open source contributers to BlogCfc include:

  1. Peter Farrell: the author of 'Lyla Captcha' that is used on this blog.
  2. Pete Freitag: the author of the 'ColdFish' code formatter that is also used on this blog.

Version:

Galaxie Blog Version 1.45 October 9 2019