Homemade Puff Pastry and Palmiers

Since the social distancing went into effect basically world wide, I’ve joined the baking bandwagon. One of my favorite things to make from scratch is puff pastry. There is something that I find just so relaxing about making the lean dough where you slowly add water a tablespoon at a time to flour that you toss in the air. Pounding out the butter is fun too.

My go to recipe with puff pastry is palmiers. They are super simple to make but tricky to get their shape just right. Essentially, you make a log out of your pastry which you then cut into these cookies. You definitely need to use parchment paper to keep them from sliding around in the oven as the butter melts however, that isn’t enough to give them that perfect heart shape. There is something that I have yet to figure out about how to shape them just before popping them in to bake. As you can tell, it is still a work in progress for me. The whole family loves them just the same. It’s a shame you can’t make a healthy version of these cookies given all the butter. That really limits how often you can make them or in my case, work on getting that heart shape.

Anyone doing the One Punch Man workout?

Well, it’s been almost a month and I know that my gym, Orangetheory, has been closed because of COVID-19. Most of us are in that camp now where we are on our own for home workouts. Running wise, that hasn’t really impacted me. I still throw on my runners and head out on the trail. It is actually nice because I am seeing more runners and starting to see frequent faces. Exercise wise, however, I’ve had to change things up a lot.

I don’t have any weights at home. My gym memberships over the years gave me a good reason to give them up. Saving space at home and always having a great set of equipment to use, the gym equation just worked for me. Without the gym, that means I got to do body weight exercises. That has led me to doing a variant of the One Punch Man workout.

One Punch Man is a hilarious anime about a super hero that can defeat his opponents with a single punch. One episode, someone asked him how he got so strong and he shared his daily workout which is:

  • 100 Push-Ups
  • 100 Sit-Ups
  • 100 Squats
  • 10 km Running

The page I linked to earlier goes into way more detail than one should about how to work up to the One Punch Man routine and even talks about what you should eat… So on my off days, I’ve been doing this variant:

  • 100 Push-Ups
  • 100 Sit-Ups
  • 100 Side Crunches
  • 100 Squats
  • 100 Lunges
  • 1 Hour Walk

I’ve been doing 5 miles twice during the week and a 9 miler on the weekend. The weather has been hit or miss but if we end up getting a good stretch of sunny days, I’ll probably add another 5 miler. It isn’t Orangetheory and I do miss my gym buddies but this simple routine is working for me.

ngrok: Accessible Self Hosting Simplified

I was trying to come up with a descriptive title for what ngrok does and that was the best I could do. Let me explain what I really mean.

Whether you are developing a micro service or Web app on your laptop, it is pretty common to want to give someone access to it over the Internet. That can be a bit of a pain as you need to look up your IP; make sure your router does the appropriate port forwarding; and confirm that you don’t have any firewalls that could get in the way. All that just to demo to someone what you are working on. Anyone that has done any amount of remote work has had to deal with this scenario.

Ngrok simplifies this whole process. It is a command line utility that sets up the necessary secure tunnels to expose the app you are running locally and registers it with an ngrok URL to make it easy to share. Let’s give it a go.

Step 1: Setup a simple Web app / service

Any app will do here. You can use one that you are currently developing or just have sitting around. In case you don’t have one, let’s spin up an instance of Elasticsearch using docker. First download the image we want to run.

docker pull docker.elastic.co/elasticsearch/elasticsearch:7.5.2

Now start it up in single node mode, a.k.a. dev mode.

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.2

Let’s check that it is running correctly by sending it a request. I am using HTTPie to do that.

http localhost:9200

You should get a successful response with a 200 status code and some information about your Elasticsearch instance.

Step 2: Install ngrok

This install is pretty painless. Download the binary from the ngrok Website.

Create an account with ngrok. Don’t worry, it’s free. You need an account to get an auth token that you will use to setup the binary that you just downloaded.

./ngrok authtoken <YOUR_AUTH_TOKEN>

If you are looking for your auth token, it should be on your ngrok dashboard.

Step 3: Expose your Elasticsearch instance

Now for the fun stuff. Let’s use ngrok to make your instance of Elasticsearch accessible over the Internet. The command below creates an HTTP tunnel on port 9200 which is the same one that our docker container is using for Elasticsearch.

./ngrok http 9200

The tunnel should start up pretty quickly and you’ll see on the console the ngrok URLs that have been assigned to it. You should get one HTTP and one HTTPS.

Account                       Chris Jordan (Plan: Free)                                                                                                                                                                                  
Version                       2.3.35                                                                                                                                                                                                     
Region                        United States (us)                                                                                                                                                                                         
Web Interface                 http://127.0.0.1:4040                                                                                                                                                                                      
Forwarding                    http://fed1a36e.ngrok.io -> http://localhost:9200                                                                                                                                                          
Forwarding                    https://fed1a36e.ngrok.io -> http://localhost:9200

Let’s send a request to one of those URLs.

http https://fed1a36e.ngrok.io

That’s it. You’ve exposed your locally running Elasticsearch on the Internet securely.

As well as the tunnel that just got setup, ngrok has a locally running dashboard that displays all sorts of useful information about requests and connections being made to your app. You can access it here: http://localhost:4040/

Closing Thoughts

Ngrok is an amazing utility especially given the current climate that many of us find ourselves in with respects to COVID-19. A lot of us are now working from home and I know it can be a bit of a struggle to be as efficient and effective as we normally are when at the office. Calling a co-worker or friend over and giving them a demo of what you are doing is just so simple and natural to do in person. Ngrok doesn’t completely replace that but it is pretty close. Probably as close as we are going to get while we are all remote. Still not the same but it does make it easy to demo what you are doing.

Be safe everyone. We’ll get through it.

Noom Friendly Instant Pot Split Lentil Soup

Another green soup just in time for St. Paddy’s Day. I am not actually a big St. Paddy’s Day fan. It just happens that my favorite soups are green. This weekend, I am at my parents’s place so I decided to make this Instant Pot lentil one for them.

This soup is great because it is a great source of veggie protein while at the same time being very Noom friendly at only 240 calories per serving. My recipe makes about 4. On top of that, it’s a throw it all in the Instant Pot and click go recipe. It can’t get any easier than that.

Thick Instant Pot Vegan Split Pea Soup

I’ve been using this pea soup recipe for a while now and it is a bit of a favorite with the kids. It is actually less of a soup and more of a mash because of how thick it is. I’m wondering if that is what makes it so appealing to them. Anyhow, I am just happy it is another way I figured out how to get more veggies in them. It is super quick and easy to make being a dump it all in the Instant Pot and click go recipe. With St. Paddy’s day just around the corner and this soup being fairly green, I figured it was a proper time to post about it.

Calling the Shopify Storefront API from a WordPress Plugin

Shopify and WordPress are great 3rd party hosting providers. Shopify lets you quickly stand up a retail Website and WordPress is solid for putting together content oriented ones, like this one. So of course from time to time, if you use both, you will want to make a deeper integration between the two. In this post, I am going to cover the basics for exactly that; setting up a WordPress plugin that interacts with the Shopify Storefront API; this plugin will let you make custom retail experiences on your WordPress site that go well beyond what liquid, Shopify’s template engine, can support while at the same time still leveraging Shopify for inventory and order management.

A WordPress plugin is where you want to do this kind of integration work. It is possible to bake this functionality directly into a theme, though, that doesn’t make a lot of sense in my opinion. It is just easier to encapsulate these kinds of integrations as plugins and then you can use them in any WordPress theme you choose.

Step 1: Setup your dev environment

To follow along here, you will need a Shopify development site. You can create as many of those for free. You can add some products to its catalog if you want but that is entirely optional for this tutorial. Doing so, however, will let you better explore the functionality of the Storefront API so it isn’t a bad idea once you have completed the steps here.

Next you should setup a development instance of WordPress. You can do that remotely with a hosting provider or you can setup WordPress locally. Local setup is my preference; you can just do things a lot faster locally. I use a Mac for development so my setup involves a MAMP environment. WordPress has instructions for that here. It is largely straightforward. Once you have MAMP up and running, download and install WordPress in the directory that your MAMP environment uses for hosting content. This tutorial is written for version 5.3.

Step 2: Create a WordPress plugin

WordPress plugin development is fortunately very easy. It can certainly get complex in a hurry, though, that is more related to the functionality that you may want to incorporate. Plugins really just boil down to some PHP with a touch of organization. The documentation is here but you can look at it later. We’re going to make a simple plugin called hello-tech. I would typically go for the standard hello-world but someone has already published a plugin with that name to the WordPress marketplace.

In your WordPress install directory, create a new plugin directory:
wp-content/plugins/hello-tech

The directory wp-content/plugins should already exist. If it doesn’t, you might be looking in the wrong spot in your WordPress install or there is something wrong with your install. hello-tech is the name of your plugin. In this new directory, create a new file call hello-tech.php. It is a good practice to name your PHP file after your plugin. In order for this file to be recognized as a plugin it needs to start with a WordPress plugin header. This header can have information about the plugin, its maintainers, and its license. However, for this tutorial let’s keep it simple and use with the following:

<?php
/**
 * Plugin Name: Hello Tech
 */

That is all your plugin needs for you to see it in the WordPress admin dashboard. It doesn’t have any functionality but you can still activate it; do that now by clicking on activate. Now we’re ready to add some functionality. Update hello-tech.php to be the following:

<?php
/**
 * Plugin Name: Hello Tech
 */
function helloTech() {
    return '<strong>hello tech</strong>'; 
}
add_shortcode('hello-tech', 'helloTech');

The above snippet does 2 things. First it creates a function called helloTech that returns an HTML snippet. Second it registers a new shortcode, hello-tech, that uses it. Shortcodes are a quick way to incorporate plugin functionality into a WordPress site. If you add [hello-tech] to the contents of any page on your site, you will see hello tech appear. There are other methods for triggering plugin functionality but we are going to stick with shortcodes for now.

Step 3: Create a Storefront Access token

You need an access token to send Storefront requests. The steps for generating a token are here.

Essentially you need to create a new private app that at least has read access to some of your store data. For this tutorial, I set the private app name to be Hello Tech. You don’t need to worry about Admin API access; you can disable all of those permissions. At the bottom of the private app settings page is where you will find the Storefront API options. Don’t forget to enable access.

Step 4: Send a Storefront API request

With the access token you can now issue Storefront API requests. Update your plugin to look like the following. Swap STORE_NAME and ACCESS_TOKEN for your Shopify store name and Storefront access token:

<?php
/**
 * Plugin Name: Hello Tech
 */
function helloTech() {
    $store_name = 'STORE_NAME';
    $access_token = 'ACCESS_TOKEN';
    $query = <<<'GRAPHQL'
    query {
        shop {
            name
            primaryDomain {
                url
                host
            }
        }
    }
    GRAPHQL;
    
    $storefront_response = wp_remote_post(
        'https://'.$store_name.'.myshopify.com/api/2019-07/graphql.json', 
        array(
            'method' => 'POST',
            'timeout' => 30,
            'blocking' => true,
            'httpversion' => '1.1',
            'headers' => array(
                'Accept' => 'application/json',
                'Content-Type' => 'application/json; charset=utf-8', 
                'X-Shopify-Storefront-Access-Token' => $access_token
            ),
            'body' => json_encode(['query' => $query, 'variables' => '']),
        )
    );

    $storefront_json = json_decode($storefront_response['body'], true);
    return '<strong>hello tech</strong><br /><br />'. 
        '<code>'.$storefront_response['body'].'</code><br /><br />'.
        '<code>'.$storefront_json['data']['shop']['name'].'</code>'; 
}
add_shortcode('hello-tech', 'helloTech');

The above plugin issues a request to get your store name, URl, and host. It is basically a hello world Storefront query that you can use to make sure your access token and plugin are working. For more information on the Storefront API and to develop queries that meet your use cases, have a look at the reference documentation.

Step 5: Move the Storefront API key into plugin settings

Our plugin now issues Storefront API requests and displays the results on a page via shortcode. Our store name and access token, however, are hard coded into the plugin. Let’s do a final touch and move those configurations to a custom settings page.

First, let’s create a separate PHP file to contain our custom settings page. Update hello-tech.php to have these 2 lines at the top to require a new file called hello-tech-settings.php:

define( 'HELLO_TECH__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );

require_once( HELLO_TECH__PLUGIN_DIR . 'hello-tech-settings.php' );

In the hello-tech plugin directory, create the file hello-tech-settings.php. Forewarning, these custom settings pages are a little verbose. The WordPress Codex provides a decent tutorial on them and you can also look at the reference documentation. They do suggest using arrays to store key/values if you are dealing with a lot of options but since we only have two, we’re going to skip that optimization. Set the contents of hello-tech-settings.php to the following:

<?php

function hello_tech_plugin_admin_init(){
    register_setting( 'hello_tech_options', 'hello_tech_shopify_store_name', 'noop_validator' );
    register_setting( 'hello_tech_options', 'hello_tech_storefront_access_token', 'noop_validator' );
    add_settings_section('hello_tech_main', 'Shopify Settings', 'hello_tech_shopify_section_text', 'hello_tech_plugin');
    add_settings_field('hello_tech_shopify_store_name', 'Shopify Store Name', 'hello_tech_shopify_store_name_setting', 'hello_tech_plugin', 'hello_tech_main');
    add_settings_field('hello_tech_storefront_access_token', 'Storefront Access Token', 'hello_tech_storefront_access_token_setting', 'hello_tech_plugin', 'hello_tech_main');
}
add_action('admin_init', 'hello_tech_plugin_admin_init');

function hello_tech_shopify_section_text() {
    echo '<p>Please set the Shopify store name and Storefront access token.</p>';
}

function hello_tech_shopify_store_name_setting() {
    $shopify_store_name = get_option('hello_tech_shopify_store_name');
    echo "<input id='hello_tech_shopify_store_name' name='hello_tech_shopify_store_name' size='40' type='text' value='{$shopify_store_name}' />";
}

function hello_tech_storefront_access_token_setting() {
    $storefront_access_token = get_option('hello_tech_storefront_access_token');
    echo "<input id='hello_tech_storefront_access_token' name='hello_tech_storefront_access_token' size='40' type='text' value='{$storefront_access_token}' />";
}

function noop_validator($input) {
    return $input;
}

function hello_tech_plugin_menu() {
	add_options_page('Hello Tech Options', 'Hello Tech', 'manage_options', 'hello-tech-settings', 'hello_tech_options');
}
add_action('admin_menu', 'hello_tech_plugin_menu');

function hello_tech_options() {
	if ( !current_user_can('manage_options') )  {
		wp_die(__('You do not have sufficient permissions to access this page.'));
    }
?>
	<div class="wrap">
        <h2>Hello Tech</h2>
        <form action="options.php" method="post">
<?php
    settings_fields('hello_tech_options');
    do_settings_sections('hello_tech_plugin');
 ?>
            <input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes') ?>" />
        </form>
	</div>
<?php
}

If you look in Settings in the admin dashboard, you should see a new entry for “Hello Tech”. Click it and you will see a basic settings page with a two field form asking for your Shopify store name and Storefront access token. Enter in those values and click “Save Changes”.

Next update your plugin to use those two options with the get_option function instead of the hard coded values. hello-tech.php should look like the following:

<?php
/**
 * Plugin Name: Hello Tech
 */

define( 'HELLO_TECH__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );

require_once( HELLO_TECH__PLUGIN_DIR . 'hello-tech-settings.php' );

function helloTech() {
    $store_name = get_option('hello_tech_shopify_store_name');
    $access_token = get_option('hello_tech_storefront_access_token');
    $query = <<<'GRAPHQL'
    query {
        shop {
            name
            primaryDomain {
                url
                host
            }
        }
    }
    GRAPHQL;
    
    $storefront_response = wp_remote_post(
        'https://'.$store_name.'.myshopify.com/api/2019-07/graphql.json', 
        array(
            'method' => 'POST',
            'timeout' => 30,
            'blocking' => true,
            'httpversion' => '1.1',
            'headers' => array(
                'Accept' => 'application/json',
                'Content-Type' => 'application/json; charset=utf-8', 
                'X-Shopify-Storefront-Access-Token' => $access_token
            ),
            'body' => json_encode(['query' => $query, 'variables' => '']),
        )
    );

    $storefront_json = json_decode($storefront_response['body'], true);
    return '<strong>hello tech</strong><br /><br />'. 
        '<code>'.$storefront_response['body'].'</code><br /><br />'.
        '<code>'.$storefront_json['data']['shop']['name'].'</code>'; 
}
add_shortcode('hello-tech', 'helloTech');

Closing thoughts

This tutorial walks you through creating a WordPress plugin that makes calls to Shopify’s Storefront API. You can also use it as a template for making other plugins that issue REST calls to a 3rd party API with relatively little effort. Once you can make that all important request and get back a response, then all you have to do is work it into a reasonable UX for your users.

New PB 12 minute treadmill run

Well, I guess I’ve been on a tear lately at Orangetheory. Yesterday they had a 12 minute treadmill benchmark run and I kind of crushed my previous best by almost .1 miles. I managed to do 1.94 miles with a negative split which I think means 2 miles is well within reach for me.

I know that treadmill running is definitely not outdoor running but I’m still pretty happy about this PB. One of the things I have noticed about my outdoor running is that while I am certainly faster these days, I do need to constantly remind myself to go faster. The nice thing about the treadmill is that you can set your pace and then just not think about it anymore. Outside, you really are on your own with your pace. There have been times where I start rocking out to a song on my phone and suddenly I’ve missed up my last mile going way slower than I should have.

My new work mug

The other week I got my February coffee club shipment from Nocking Point. This time in addition to my light and dark roast beans, I got this mug. I’m kind of digging it and it has taken over as the primary one that I use at work. My old mug is this NPR one I got about 10 years ago while I was still living in New York. I guess I was about due for a change.

They also switched up the coffee roaster to Rockabilly, another small batch operation. I’m working on their light roast and it is great. So far I’ve been super happy with this coffee club.

200, 000 Orangetheory calories burned

Last night, I hit a bit of a milestone with my Orangetheory workouts. I broke the 200k calories burned mark for all time. I’ve been going to Orangetheory for over two years now to augment my running. I have found it to be a great way to get my core strengthening and speed training done. The 200k number is a little too big for me to quantify on its own beyond just thinking that I have burned a ton of calories. So I’ve googled some cheat day foods to make it more real. Here’s a small list of things I’ve come up with so far. Grapes clearly aren’t a cheat day food but I put them on there to give some perspective to the others. Junk food is junk:

  • 76 large Dominos Hawaiian pizzas
  • 99 plates of Applebee’s neighborhood nachos with beef
  • 175 Costco cheeseburgers
  • 220 Chipotle carnitas burritos with sour cream and cheese
  • 315 bottles of red wine
  • 362 Costco hot dogs
  • 526 Starbucks grande pumpkin spice lattes
  • 2, 198 Oatmeal chocolate chip cookies
  • 34, 483 Cadbury mini eggs
  • 58, 824 M&Ms
  • 100, 000 grapes

Marshmallow Fondant Is A Thing

We recently celebrated one of my kid’s birthdays and I decided to try to up my baking game. I discovered that you can easily make fondant out of marshmallows which is pretty mind blowing for me. Fondant has always been one of those things that I’ve steered away from since you could only buy small packets of it at the store and making it from scratch was a fairly involved process. This marshmallow based recipe I have essentially only needs marshmallows, powdered sugar, and a microwave.

Working with fondant is a lot of fun. It is really just edible Play-Doh. I made these froggie cupcakes and I don’t think they are that bad for a first attempt. In hindsight, I’ve realized that working with a cake as opposed to cupcakes would have been easier. This is a case where bigger is simpler. I’m definitely going to be messing with fondant for the next birthday.