100 Ways to Work Out Loud
https://discoverpraxis.com/100-ways-to-work-out-loud/Archived Link
100 Ways to Work Out Loud
https://discoverpraxis.com/100-ways-to-work-out-loud/Archived Link
On a recent episode of Office Hours, a listener asked about the purpose of social media. Isaac and TK recommended taking a pragmatic approach. Here is my take on what that looks like.
Hereâs how I use the major social channels:
I like Facebook less every week. I only hop on a few days a week now. The content there is mostly trash. I go on to keep up with friends from high school and college, as well as family. I rarely comment and I almost never engage in a discussion there. It isnât as toxic as Twitter because you generally have closer ties with someone involved in the thread on Facebook, but it is still usually bad.
I think people waste too much time on Facebook unintentionally and would do well to delete the apps from their phones and only check it from one specific device that you use only as a secondary or tertiary device. For me that is my iPad. I keep Facebook blocked on my computer and my phone to reign in my unintentional time wasting.
Twitter is my second favorite social service to browse. It is where I get a lot of recommendations, find out about new apps, and get my news. I donât read traditional news outlets unless I find an interesting story linked on Twitter or a blog I read (see below).
I curate who I follow pretty regularly, so I have a pretty good âcontent to garbageâ ratio, or at least one Iâm willing to tolerate enough to check out during breakfast and lunch.
I still want something like Mastodon to take off, but I havenât found any communities that are active enough to invest in. I prefer using the internet as a place to consume (find recommendations, keep up with what friends and family are doing, learn new things) and project (write and share my own stuff), but not converse. Most of the internet is a terrible place for conversing. It just isnât set up for that. Perhaps Mastodon can fill that gap if I find the right community?
Iâm trying out https://refactorcamp.orgArchived Link right now and having a pretty high hit rate of good content. Still not great for discussion, though.
If you have any Mastodon communities you recommend, Iâd love to hear about them.
Iâm photographer. I love posting to Instagram. It is probably my favorite social service to browse, too. So much good stuff in my feed! That said, it is the one Iâm most likely to waste too much time on because I like it so much. So I delete it from my phone most of the time and only download it when I want to post to it, keep it around for a few days with 15 minute time limits set with Screentime, then delete it until I want to post again.
Oh, Reddit. I want to love you, but I canât. The comments are so toxic, even in decent subreddit communities. Every subreddit I start getting involved in inevitably devolves to inside jokes, gatekeeping, and beginners asking the same question covered hundreds of times. (On the Kombucha sub, it is always âis my scoby okay?!?!). It gets tiring.
I love reading AMAs, but I never get there in time to ask a question. And when I did ask questions in AMAs a few times, I got banned for asking for a month because I asked the same question each time: What are you reading right now? Apparently that isnât allowed.
Also, the search is completely terrible. There is probably tons of useful stuff locked away in threads that no one can find, forever lost to the ether.
Iâm over Reddit. My RescueTime stats show that I visit the site less and less each year.
I donât use Pinterest. I canât reliably find anything in that awful sea of ubiquitous images. You have to sift through a pile of garbage to find one useful thing. I prefer to avoid the whole mess in favor of other services. I use http://Are.na as a personal pinboard.
I only watch YouTube videos I find embedded elsewhere or that someone sends me. I canât remember the last time I went directly to YouTube.com to just see what was happening. I donât like the video medium unless Iâm trying to learn something, and I tend to find those videos through search engines. I donât watch YouTube videos recreationally.
This is too small right now to be super useful, but Iâm hopeful for it. A service dedicated to book, show, and restaurant recommendations. Requests for this sort of thing on regular social media tend to get lost in the sea of other garbage and algorithmic timelines, so people often donât respond until days later. Likewise keeps these asks front-and-center. You should join me on Likewise! https://likewise.com/invitedby/5bbe223985965466d44255eb
Great tech news source. I donât participate in the comments/community there. Iâll often click through to the comments section to get a tl;dr of the article or get hot takes on current events. I find a lot of products and tools here that I bookmark and end up using or recommending later.
There was a period where I checked Product Hunt daily and found a lot of cool stuff there. Now I check it maybe once a week and only find a fraction of the cool stuff I once found there.
I hate it. I refused to be on it for years. I have a profile now to set a good example for Praxis participants, and I may even cross post one of my articles there, but I get very little value from the service.
I went through a phase where I answered questions on Quora, but I got bored by it pretty quickly. I didnât invest enough to get over the hump and get a large return, so it just felt like I was wasting my time. Plus, there are so many shitty answers on there by people who just spend all day answering questions they only know a little bit about. Costless question asking and costless answering lead to a pretty low quality of content. The early days were cool because it was costlier to be in a small community like that instead of elsewhere. But now it sucks.
Iâve never asked a question on SO, but I sure am glad it exists. Iâve had dozens, maybe hundreds, of questions answered by previously existing questions there. I have chipped in and answered some questions there, but I donât make a regular habit of it.

I have a certain capacity for creative output. That level may increase or decrease over time, but it stays relatively constant day-to-day.
You can think of this capacity as tokens that I have available to spend each day. I can either spend these tokens at my full-time job, at a side gig, or on a personal project.
I feel most balanced when I use 80% of my creative capacity at my full-time job and 20% elsewhere.
When I use 100% of my capacity at my full-time job for an extended period of time (say 2 weeks or more), I feel unbalanced. My overall creative capacity starts to decline. Some might call this feeling burned out.
When I use more than 20% on personal projects or side gigs (i.e. less than 80% at work) for more than two days in a row, I feel unbalanced, like I’m neglecting my work responsibilities. Like I’m falling behind and my output isn’t up to par.
I’ve never taken complete breaks from creating things. The manifestation just tends to shift. On vacations I tend to pick up photography and journaling to fill the creative gap. Sometimes drawing. During the holidays I tend to make more elaborate meals and try making new cocktails.
I’ve also never shifted 100% of my capacity into personal projects for an extended period. I haven’t been unemployed for more than a week in the past 7 years. Vacations are breaks from personal projects as much as traditional work, so that is why the output tends to shift to photography, journaling, and drawing.
I routinely go 3-4 weeks at a time at a 95/5 split on work/personal. Those times my personal creative output tends to be listening notes from podcasts and cooking. Days during high work periods where I manage to put out a longer blog post, I’m almost certainly eating leftovers or takeout. (Tonight, for instance: 3 blog posts plus curating a bunch of book recommendations on Likewise and I ate leftover soup for lunch and made a taco salad from leftovers in the fridge for dinner.)
I radically cut down the amount of side gigs I take on in order to prioritize personal projects. In fact, I have no side gigs going on at the moment.
What would my creative output look like when focused 100% on the personal side? I haven’t experienced that since high school and college, but the photography projects I focused on during those periods still rank among what I consider my best. Even periods where I’ve shifted to a 20/80 split on work/personal resulted in projects I’m proud of and look upon fondly.
In the next few years, I’d like to take a complete month away from full-time work and focus on personal projects for the entire time. Deliberately throw myself out of balance in a way I’m not used to and see what I create.
Creative people commonly lament about being “blocked,” perpetually stuck and unable to produce work when necessary. Blocks spring from the imbalanced relationship of How and Why: either we have an idea, but lack the skills to execute; or we have skills, but lack a message, idea, or purpose for the work. The most despised and common examples of creative block are the latter, because the solution to a lack of purpose is so elusive. If we are short on skill, the answer is to practice and seek outside guidance from those more able until we improve. But when we are left without something to say, we have no choice but to either go for a walk or continue suffering in front of a blank page. Often in situations like these, we seek relief in the work of others; we look for solace in creations that seem to have both high craft and resounding purpose, because they remind us that there is a way out of the cul-de-sac we have driven into by mistake. We can, by dissecting these pieces, begin to see what gives the work of others their vitality, and better understand the inner methods of what we produce ourselves. If we are attentive, with just a dash of luck, we may even discover where the soul of our own work lies by having it mirrored back to us in the work of others.
But we must be careful not to gaze too long, lest we give up too much of ourselves. Forfeiting our perspective squanders the opportunity to let the work take its own special form and wastes our chance to leave our fingerprints on it. We must remember Why we are working, because craft needs objectives, effort needs purpose, and we need an outlet for our song. If we stay on the surface and do not dig deep by asking Why, we’re not truly designing.
Podcast: http://longform.org/posts/longform-podcast-311-jerry-saltz
Notes:
1: The Value of Debate, Is Self-Improvement Overrated, and Dealing with Haters
Notes:
2: What to Ask In a Job Interview & Is It Worth it to Help Unmotivated Friends
Notes:
Cameron Sorsby asked the Praxis staff today what our top 3-5 favorite movies are, off the top of our heads. I came up with 3 easily, but none were recent. Then I realized that no movie I’ve watched for the first time in the last four years is memorable. Series are getting so much better and eclipsing movies since they are free from networks and ad breaks.
What will the next leap forward for movies look like? Netflix/Amazon Prime hasn’t changed much for that format. What’s next?
Podcast: https://www.buzzsprout.com/126848/814311
Notes
Podcast:
Notes:
Happiness isn’t our natural state, and that is okay. You just have to take deliberate steps to get there.
Why you need to stick it out in one position for two years.
Ways to build your personal brand, featuring examples from the Praxis community.
https://discoverpraxis.com/compound-career-opportunities/Archived Link
Ways to build your personal brand, featuring examples from the Praxis community.

So, you are learning Python and want to build a portfolio that helps you land your first technical job at a company. Here are some project ideas for building your portfolio.
https://discoverpraxis.com/portfolio-project-ideas-python/Archived Link
College degrees donât send the signals they once used to. You have to take charge of building your personal brand and work out loud instead. Here are ten ways to build your brand.
https://discoverpraxis.com/10-ways-build-personal-brand/Archived Link

What if you didn’t have to copy, switch window, paste, switch window, copy, switch window, paste, switch window, copy, switch window, and paste just to copy multiple items? With a clipboard manager, you don’t have to.
https://www.youtube.com/watch?v=i74J0n650QQ

So you have a job offer from another company and are ready to leave your existing role. You want to leave without burning the social capital you’ve built up over time. What do you do?
First, relax. Having that first conversation with your manager is usually nerve wracking, but everything will be okay. Switching jobs is expected, and chances are that your manager has been on both sides of the table before. Follow these guidelines below and you’ll be on your way to your new gig in no time.
http://discoverpraxis.com/how-to-leave-your-job/

I started this blog ten years ago today. I was in a room at the Doubletree in Tarrytown, NY. It was a Sunday and it was the weekend in-between my first FEE seminars. I ordered a pizza and some ziti from Capri Pizza and decided to tear down my old HTML site and give blogging a try. I figured out how to install WordPress 2.5.1 and went to town. Here is what the site looked like:

Here is the post that started it all.
Since then, I went on to work at FEE and move to NY, passing that Doubletree regularly. I blogged for a year straight. Iâve lived in 5 different cities and posted from every single one. Iâve written 763 posts on this blog since then and I average about 20,000 unique visitors a month according to my server logs.
The blogging has paid off. Here are things that have come from my blogging and showing my work:
Also, not only is today my 10 year blogging anniversary, it is also my 5 year wedding anniversary! Amanda and I had just started dating when I put this blog up, so sheâs been here since the beginning. Little did I know that weâd get married exactly five years later.
Itâs been a fun ten years and Iâm not done yet. cagrimmett.com is here to stay. Check out my archives and stay tuned for more.

During the Praxis bootcamp, participants are expected to make every single day a non-zero day. Most participants ask us to hold them accountable, so they email one of our staff each day and that person emails them the next day if they miss a check-in. This takes an enormous number of emails, staff overhead to keep track of, and is difficult to search. Isaac asked me, “What can we do to automate this?”
It needs this functionality:
There are existing systems that do this sort of thing, so why make our own? During the bootcamp, our customers use what we call The Portal, which is a curriculum platform I built on top of WordPress with the help of Restrict Content Pro and wpcomplete. I didn’t want to add another destination into the mix. I wanted a reason for customers to go to the Portal every day and keep their work moving forward. Plus, they already have logins there. No need to add yet another login for them to keep track of.
USP Pro handles all sorts of complexity when it comes to submitting posts from the front-end of a WordPress site: The form, the custom post type, assigning the current logged-in user to be the author, and displaying success and error messages. They also have hooks and filters to make using the posts in templates easier.
I used a custom template to hide some of the things I’d need to make the whole process work: User ID to assign as the post author, name and today’s date for the title of the post.
After the form, we also want to show all the posts someone has already submitted. I do that with a WP_Query_ Note: I added a Delete button here in case some makes an accidental post. If you want someone to be able to delete their check-in post, they need to have the role Author.
Here is the code I used for the template and comments about what it does:
// Check if user is logged in. Display the check-in form if so, login form if not. if ( is_user_logged_in() ) { //Get the logged in user, today's date, and the PHP session ID $current_user = wp_get_current_user(); $today = date("F j, Y"); $ses_id = session_id(); ?> class="usp-pro-form"> id="usp-pro" class="usp-pro usp-form-4102"> class="submitted-checkins"> Your submitted check-ins: // Show posts from this user ID with the type usp_post $post_query = new WP_Query( array( 'post_type' => 'usp_post', 'author' => $current_user->ID, 'orderby' => 'date', 'order' => 'DESC', ) ); if ( $post_query->have_posts() ) : while( $post_query->have_posts() ) : $post_query->the_post(); ?> post_class(); ?>> the_time('F j, Y \a\t g:i a') ?> endwhile; else: echo "You have no check-in posts. Submit one above!
"; endif; ?> } else { ?> style="padding:50px;"> echo do_shortcode('[login_form]'); ?> } ?>
The page (with a little bit of CSS added, which I’ll leave as an exercise for the reader) looks like this: 
This goes in functions.php:
add_action( 'show_user_profile', 'accountability_opt_in' ); add_action( 'edit_user_profile', 'accountability_opt_in' ); function accountability_opt_in( $user ) { ?> Daily Accountability class="form-table"> type="checkbox" name="checkin" id="checkin" if (get_the_author_meta( 'checkin', $user->ID) == 'True' ) { ?>checked="checked" }?> value="True" />
/> class="description">Yes, opt me in.
} add_action( 'personal_options_update', 'save_accountability_opt_in' ); add_action( 'edit_user_profile_update', 'save_accountability_opt_in' ); function save_accountability_opt_in( $user_id ) { if ( !current_user_can( 'edit_user', $user_id ) ) return false; update_usermeta( $user_id, 'checkin', $_POST['checkin'] ); }
So, at the bottom of the user profile, it now shows this: 
Outline:
I like to leave the echos on for debugging if something goes wrong. Like, for example, if you use the_date instead of get_the_date and occasionally get NULL instead of a date and can’t figure out why. (Hint: the_date only fires once in a loop. Thanks for the help debugging, Eric Davis!)
Also, I know I’m using two different types for formatting for if statements. It helps me keep them separate.
$key = $_GET['key']; if ($key == 'RANDOM_KEY' ) { require_once($_SERVER['DOCUMENT_ROOT'] . '/wp-load.php'); function get_user_by_meta_data( $meta_key, $meta_value ) { // Query for users based on the meta data $user_query = new WP_User_Query( array( 'meta_key' => $meta_key, 'meta_value' => $meta_value ) ); // Get the results from the query, returning the users $users = $user_query->get_results(); return $users; } $opted_in_users = get_user_by_meta_data( 'checkin', 'True'); foreach ($opted_in_users as $user) { echo $user->ID . ' ' . $user->user_email . '
'; $post_query = new WP_Query( array( 'post_type' => 'usp_post', 'author' => $user->ID, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC', 'showposts' => '1', ) ); // The Loop if ( $post_query->have_posts() ) : while ( $post_query->have_posts() ) : $post_query->the_post(); $date = get_the_date('U'); echo 'last post date: ' . $date . '
'; //echo 'now: ' . time() . '
'; if( $date > (time() - 100800)) { echo 'Within 28 hours
'; continue; } else { echo 'Not within 28 hours
'; // Initialize curl $curl = curl_init(); $data = array( 'user_id' => $user->ID, 'email' => $user->user_email, 'first_name' => $user->first_name, 'last_name' => $user->last_name, 'last_post' => $date, ); $jsonEncodedData = json_encode($data); $opts = array( CURLOPT_URL => 'https://hooks.zapier.com/hooks/catch/1503890/aqztv5/', CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $jsonEncodedData, CURLOPT_HTTPHEADER => array('Content-Type: application/json','Content-Length: ' . strlen($jsonEncodedData)) ); // Set curl options curl_setopt_array($curl, $opts); // Get the results $result = curl_exec($curl); // Close resource curl_close($curl); echo $result; } endwhile; else : echo "No posts
"; // Initialize curl $curl = curl_init(); $data = array( 'user_id' => $user->ID, 'email' => $user->user_email, 'first_name' => $user->first_name, 'last_name' => $user->last_name, ); $jsonEncodedData = json_encode($data); $opts = array( CURLOPT_URL => 'https://hooks.zapier.com/hooks/catch/1503890/aqztv5/', CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $jsonEncodedData, CURLOPT_HTTPHEADER => array('Content-Type: application/json','Content-Length: ' . strlen($jsonEncodedData)) ); // Set curl options curl_setopt_array($curl, $opts); // Get the results $result = curl_exec($curl); // Close resource curl_close($curl); echo $result; endif; } } else { exit("You are not authorized. Go away."); } ?>
Viewing posts in the wp-admin area is less than ideal. They are grouped by date instead of author and the full contents doesn’t show unless you click. No want to view updates at a glance. So I made a template for that.
// First, check if user is an admin. if ( !is_user_logged_in() || !current_user_can('administrator') ) { wp_redirect( site_url() ); exit; } else { // User IDs are passed via query string. If no string, show all names $user = $_GET['id']; if ( $user == null ) {?> Participants who have submitted check-ins: $args1 = array( //'role' => 'author', 'orderby' => 'first_name', 'order' => 'ASC' ); $authors = get_users($args1); foreach ($authors as $user) { $user_post_count = count_user_posts( $user->ID , 'usp_post' ); if ( $user_post_count > 0) { echo '. $user->id . '">' . $user->first_name . ' ' . $user->last_name . '
'; } } } else { $user = get_user_by('id', $user); $post_query = new WP_Query( array( 'post_type' => 'usp_post', 'author' => $user->ID, 'orderby' => 'date', 'order' => 'DESC', ) ); ?>
/> href="/check-ins/">← Back to all participants with check-ins
echo $user->first_name . ' ' . $user->last_name .'\'s check-in posts';?> if ( $post_query->have_posts() ) : while( $post_query->have_posts() ) : $post_query->the_post(); ?> post_class(); ?>> the_time('F j, Y \a\t g:i a') ?> the_content(); ?> endwhile; else: echo "You have no check-in posts. Submit one above!
"; endif; } }
Here is what the template outputs:


The best way to do this is to hook in to when the post type is initiated and toggle the ‘exclude_from_search option so ‘true’. I added this to functions.php:
add_action( 'init', 'usp_post_hide_search', 99 ); function usp_post_hide_search() { global $wp_post_types; if ( post_type_exists( 'usp_post' ) ) { // exclude from search results $wp_post_types['usp_post']->exclude_from_search = true; } }
I opted to use Zapier for two things:
wp_cron isn’t super reliable if you need something to run at a given time, and since I’m hosting on WPengine, I don’t have access to the server cron. We already use Zapier for a ton of stuff, so I fire off a GET to my script with the query string random key.Here are a few ways I want to improve this when I have time:

Praxis alumni Nate Baker and Nick Rundlett both became new managers this month. Congrats, guys! Nate asked the community for tips on how to be a good supervisor. Here is what our advisors and alumni had to say.
https://discoverpraxis.com/12-tips-for-new-managers/Archived Link

Yesterday my friend Derek Magill asked the Praxis community, âWhat books have had the most impact on your career/education?â
I love this question. Notice the use of the word impact. He isnât asking for your favorite books, the books you recommend on a specific subject, or the books you agree with the most. He is asking for the books that have had a significant impact on your education. Books that influenced and changed the way you think and interact with the world.
Here is my list, in order of when I read them. I explain what impact they had on my education and how that shifted the way I interact with the world.
https://discoverpraxis.com/16-books-shaped-interact-world/Archived Link

I made a video that shows you how to send custom conversion events to Facebook whenever a visitor, lead or customer engages with one of your websiteâs calls-to-action â all without having to touch your websiteâs code. It was featured on the ConvertFlow blog!
Check it out here: https://convertflow.com/blog/how-to-use-convertflow-with-your-facebook-ad-campaigns/Archived Link

Reamde is a wild ride that traverses half the globe, has multiple storylines intertwined, and jumps back and forth from the virtual and physical world. Stephenson is a captivating writer who pulls you into the story. He makes 1000+ pages feel like 300.
Check it out here: http://cagrimmett.com/book-notes/reamde_neal_stephenson/

When I migrated all of my old posts to Jekyll, my build time skyrocketed. The average time was 39 seconds for 853 posts. Abysmal. This is especially annoying when I’m actively working on the site with jekyll serve and waiting 40 seconds for changes to reflect.
The first step to figuring out what takes so long is running the Liquid profiler: $ jekyll build --profile
This is what it output for me:
Filename | Count | Bytes | Time --------------------------------------------------------+-------+----------+------ _layouts/default.html | 853 | 9652.42K | 7.462 search/feed.json | 1 | 1394.16K | 4.148 _includes/header.html | 853 | 1230.35K | 3.485 _layouts/post.html | 755 | 5119.00K | 2.301 _includes/opengraph.html | 853 | 870.67K | 1.694 _includes/icons.html | 810 | 1752.89K | 1.454 sitemap.xml | 1 | 203.34K | 1.321 _includes/footer.html | 853 | 109.12K | 0.273 til/posts.yml | 1 | 14.27K | 0.147 about.md | 1 | 18.02K | 0.085 _posts/2016-07-04-posts-heatmap-calendar.md | 1 | 16.78K | 0.080 isotope.html | 1 | 389.52K | 0.048 _layouts/book.html | 34 | 198.47K | 0.039 til.md | 1 | 58.76K | 0.023 feed.xml | 1 | 139.11K | 0.022 ... with a dozen more tiny blog index pages from paginator done in 39.359 seconds.
I tried a bunch of random stuff that made tiny improvements before I started doing research: Removing extraneous files, cleaning up if blocks that I no longer used, hardcoding things in the header that relied on variables from _config.yml, etc. None of this made significant improvements. I had already moved extraneous plugins long ago and I keep Jekyll up to date, so there was nothing more to do there.
I eventually came across this post by Mike Neumegen, which mentioned jekyll-include-cache, which caches the files you tell it to with the first instance and then serves the cached versions up for subsequent requests. For includes that don’t change based on the page content, you can replace {% include example.html %} with {% include_cached example.html %}. When I did this with my sidebar, nav bar, and footer, it cut my average first build time to 28 seconds, with subsequent regeneration times around 19 seconds. Awesome! (Neumegen’s post, which mentioned jekyll-include-cache contains a lot of other helpful advice for Jekyll build optimization. Check it out!)
My next step was to look at other includes to see if I could shave more time off. Some files had a mix of static and dynamic assets, so I split out all of the static assets into more include_cached includes. This cut another 5-6 seconds off of my build time. Boom.
Now that my layouts and my includes were as optimized as I could get them without major rewrites, I turned to the next major time hog: search/feed.json. 4 seconds for a single file! This file loops through everything on the site and dumps it into a single file so that I can crawl it with Javascript to power search on my site.
I used Mat Hayward’s search project with a few tweaks. As I dug deeper on the specific functions in the feed.json generator, I noticed that everything was being converted from Markdown to HTML first, then HTML stripped out, then turned into JSON. I wondered if skipping the markdown conversion step would lead to inaccurate search, so I tried it. Not only did my search function the same, but it dropped feed.json’s build time down to around a sixth of a second.
My build time now looks like this:
Filename | Count | Bytes | Time --------------------------------------------------------+-------+----------+------ _layouts/default.html | 853 | 9564.71K | 2.922 _includes/head.html | 853 | 1571.79K | 2.623 _includes/opengraph.html | 853 | 870.67K | 2.171 sitemap.xml | 1 | 203.34K | 1.177 _layouts/post.html | 755 | 5195.80K | 0.509 search/feed.json | 1 | 1394.65K | 0.176 _posts/2016-07-04-posts-heatmap-calendar.md | 1 | 16.78K | 0.091 about.md | 1 | 18.02K | 0.076 isotope.html | 1 | 389.52K | 0.050 _layouts/book.html | 34 | 198.47K | 0.030 _includes/header.html | 1 | 1.43K | 0.021 til.md | 1 | 58.76K | 0.019 feed.xml | 1 | 139.24K | 0.018 ... with a dozen more tiny blog index pages from paginator done in 19.594 seconds.
Regeneration times when running jekyll serve are hovering around 13 seconds now, which is a significant quality of life improvement for me when managing this blog.
There is probably more work I can do with moving the highlighter to the front end with JS and simplifying the Liquid in head.html and opengraph.html, but I’m stopping here for now.

Today I installed Craft CMS in for a new Praxis project. I use Laravel Homestead for my local development environment. It installs like pretty much every other PHP app on Homestead (use this guide by Matt Collins if you aren’t very familiar with Homestead), but I ran into a few annoying errors along the way:
If Mcrypt is required shows when you first go to http://yoursite.local/admin to finish the install, it is probably because you are a good citizen and your Homestead box is actually up to date, running PHP 7.2 as the default. Here’s the issue: mcrypt was removed from PHP 7.2. Craft 2 still needs it. There are three solutions:
Homestead.yaml, set the php variable to php: "7.0" under your site in the Sites block. Here is what mine looks like:- map: craft-praxis.local to: /home/vagrant/craft-praxis/public php: "7.0"
If you see this message, chances are that you are using MySQL 5.7.5+, which changed the way it deals with GROUP BY. See this StackOverflow post for the two solutions: Removing the ONLY_FULL_GROUP_BY option from sql_mode or adding the initSQLs database config settings in craft/config/db.php.