Hi! I’m Brad!

I’m an award-winning software developer from Laramie, Wyoming.

Category: Uncategorized

  • Sustainable Styles: An Object-Oriented twist on BEM

    I have been working in the web for a long time, and I have worked full-time professionally at UL for almost 5 years.  In that time, I’ve learned a lot about how developers perceive CSS, and why so many projects are absolutely littered with novice-level CSS.

    BEM was introduced a few years ago to deal with one of CSS’ biggest problems: taxonomy, the art of naming things.  Its primary goal was the provide a sane, sustainable method for writing class names.  Another goal was to create a sustainable approach for changes in state..  For example, BEM provides an answer for “How do we style a blog post (block) that is featured (modifier)?”  Consider some of these candidates

    .blogPostFeatured {}
    .blog-post.featured {}
    .blog .post.featured {}

    None of these fully address the application of a block-specific featured state, and the intended portability of a CSS class. BEM methodology here is going to be as atomic as possible with components (like a post), and as verbose as possible to avoid collisions.  For example, using .featured with .blog is fine, but what if another entity, like .page comes along, and also uses the .featured class?  What happens when these two entities (posts and pages) need different styles for featured?

    Tweaking .featured for one entity will also affect the other.  Unintended changes across the app lead to what I call this the Pick Up Sticks problem.  For this reason, using verbose Modifiers is the solution to the problem.  Consider the following SCSS. Notice that .post--featured only works with .post, and so the modifier’s effect is isolated to the block.

    .post {
        &.post--featured {} // => .post.post--featured
    .page {
        &.page--featured {} // => .page.page--featured

    Now, examine the accompanying HTML markup…

    <!-- Works great! -->
    <div class="post post--featured"></div>
    <div class="page page--featured"></div>
    <!-- Featured states have no effect when misapplied -->
    <div class="page post--featured"><div>
    <div class="post page--featured"></div>

    Essentially, this creates namespaces for the .page and .post blocks, and any of the modifiers for these blocks are useless outside of the associated namespaces.  This is a powerful, clean, sustainable approach that will help you tame and harness the cascade, and master CSS.

    Styling relationships

    When parent-child relationships exist within a data model, it is common to see that relationship reflected by markup and styles. Consider the following data model, written in TypeScript.

    class Post {
        public comments: Comment[];
    class Comment {}

    It’s easy to see that Post has many Comment, as indicated by the Post.comments array of Comment objects. How do we turn this into a sustainable CSS design system?

    First, start with two root-level selectors to represent the Post and the Comment.

    .post {}
    .comment {}

    Since Post has a property to contain many comments, represent this relationship in with an Element (preceded by two underscores) in the SCSS:

    .post { // block
        .post__comments {} // element
    .comment {} //block

    Have a look at the markup that could be styled by this stylesheet…

    <div class="post">
        <div class="post__comments">
            <div class="comment">…</div>
            <div class="comment">…</div>
            <div class="comment">…</div>

    So far so good!  It’s clean, easy to understand, easy to maintain, and it’s only the slightest bit verbose.  You can see that the Post block contains a Post Comments Element, and we put many Comment blocks into the Post Comments Element.

    Let’s continue to style two Comment blocks when they are next to each other in the Post Comments Element…  We can use a variant of the lobotomized owl to create a simple spacing system that doesn’t bring unnecessary gaps of whitespace in our page.

    .post {
        .post__comments {
            > .comment + .comment {
                margin-top: 1.5rem;

    Styling boolean states

    Next, consider representing boolean states on a Block.  The boolean test might look like this…

    class Post {
        comments: Comment[] = [];
        get hasComments(): boolean {
            return this.comments && this.comments.length > 0

    The boolean is represented in SCSS as a Modifier:

    .post {
        .post--has-comments {} // post.hasComments() === true
        .post--no-comments {} // post.hasComments() === false
        .post__comments {}

    When the post has comments, our markup will represent this by including the modifier with the block:

    <div class="post post--has-comments">
        <div class="post__comments">
            <div class="comment">…</div>
            <div class="comment">…</div>
            <div class="comment">…</div>

    We are now able to modify the Post appearance, as well as the children, when the has-comments modifier is added:

    .post {
        // post.hasComments() === true
        &.post--has-comments {
            background: url('comments-icon.png') top right;
            // post.comments when post.hasComments
            .post__comments {
                border: solid 1px #ccc;
        // post.hasComments() === false
        &.post--no-comments {
            .post__comments { display: none }

    The has-comments state can be used to leverage the cascade (the C in CSS), to further affect descendant elements, without a bunch of bloat.

    <div class="post post--has-comments">
        <div class="post__comments"></div>

    Our class names are written to represent our schema, its relationships, and its states.  This prevents the pick-up sticks problem, and makes the entire project easier to style.  Consider a new scenario where a blogging platform allows multiple blogs to exist, so we need to style a series of posts…

    class Blog {
        title: string;
        posts: Post[]

    No problem! We already have styles for Post so we just need to author the styles for the Blog block which contains many Post blocks. We’ll add a simple spacing rule, and some nice styles for a title. We also benefit from the styles that were written for Comments within Post.

    .blog {
        .blog__title { font-weight: bold; font-size: 2.5rem; }
        .blog__posts {
            // within .blog__posts, any direct-descendant post that is 
            // after any post gets a margin-top to space things out
            > .post + .post { margin-top: 1.5rem; } 

    By being verbose, and using a reliable strategy to map state and schema to CSS appearance, we avoid a host of architectural issues that have been confusing developers for decades.

    Putting it together

    Here’s a cheat sheet to help apply BEM methodology to the mapping of objects to class names.

    When you’re styling…Use…For example…
    A business entity (a row in a database)
    a Block
    A property on an entity (a column in a database)
    an Element
    A child relationship
    an Element filled with blocks
    .post__comments > .comment + .comment
    .comment__author > .user
    A state
    a Modifier
  • Creating an Invisible Application: Adding email as an interface for an application

    This post is designed to serve as a brief technical overview of a recent feature added to ServiceSpark, a community service management platform I develop as a volunteer for the United Way of Albany County.

    ServiceSpark uses email to send email notifications to volunteers about new events and new comments on events that the volunteer is connected to.  The email includes a link back to ServiceSpark.org, and encourages the user to RSVP and comment on the event.  Unfortunately, however, this requires a click, a login, and users rarely follow through with the process.

    The Challenge

    Use email as an interface for ServiceSpark, allowing users to “reply” to an email to leave comments, or allow users to RSVP using their client’s native calendar support.

    The Implementation

    My implementation of this required some sort of way to generate unique reply email addresses for each email that was sent, and a way to make note of the reply address, so that replies, if any, can be processed.

    Dealing with the reply is also problematic.  Many replies include the chain of emails behind the reply, or signatures.  These artifacts need to be stripped from the application, or else the comments will become cluttered.

    Emails also need to be attached to the user’s ServiceSpark identity.  Every message should come in and appear as if the volunteer logged into ServiceSpark and created the comment, or submitted an RSVP manually.

    But, finding a way to receive email at any possible address seemed challenging. For starters, standardizing a way to communicate with an email platform is difficult.  Hijacking qmail, or some other mail queue is just tedious and feels like a kludge.

    The Tools

    Receiving emails turned out to be easy with Mandrill.  Mandrill has an “incoming message API” that allows for your application to receive email via webhooks.

    Briefly, this is how Mandrill works

    1. Set up a custom reply domain.  This is a DNS MX entry that will set Mandrill as handler for a custom domain.  This takes about 5 minutes.
    2. Set up a route from your Mandrill dashboard.  This maps incoming messages to a webhook on your server.  For mine, I set up a wildcard, so that all addresses get sent to the webhook.
    3. Emails received by Mandrill will be pushed as a JSON object to your server in nearly real time.

    Since I’m using CakePHP, which is MVC, I set up a controller that is a singularized endpoint for all incoming webhooks.  A token is used as a shared secret for the application and Mandrill.

    1. Application receives a POST at /webhooks/incoming/<token>
    2. Application fires an event `Webhook.Incoming.<token>`
    3. An event handler is set to listen to `Webhook.Incoming.<token>` and parse the incoming data.

    Once the webserver was receiving messages from Mandrill, I began work to parse the messages.  Dealing with the “junk” in email, like signatures, and threads was a huge requirement.  Posting this information publicly would clutter the application greatly, and annoy users.

    GitHub to the rescue–literally!  GitHub wrote an email reply parsing library, and the library has been ported to PHP.  Including this library and parsing the text from the Mandrill request was trivial.

    Mapping the incoming email address to a specific action is accomplished by a database table that has fields for GUID, user_id, event_type, and event_data.

    So Far

    1. Emails are generated with special GUID@myreplydomain.org Reply-to addresses.
    2. GUIDS and the corresponding event information are saved to the database.
    3. User receives an email.  If they would like to respond, they may do so using their email client.  Replies go to <guid>@myreplydomain.org.
    4. Emails are received by Mandrill, parsed and sent as a JSON object to a webhook on my web server.
    5. The server looks up the guid and processes the email appropriately.

    At this point, email to comment is working beautifully.  The next challenge is sending valid meeting requests and processing the responses into the application.

    Standards are your friend.

    The global standard for calendar data exchange is ICS aka ICAL.  This text format specifies events, and recipients, and metadata to allow loosely-coupled applications to synchronize state (like meeting cancellations).

    There is a protocol to using ICS/ICAL to exchange event information.

    ICS/ICAL crash course

    1. Lines are allowed to be 75 characters long.  If your line needs to wrap, the next line should start with a space.  Ideally, you should construct your file, and then wrap the lines one at a time at the end.
    2. ICS files start with BEGIN:VCALENDAR and end with END:VCALENDAR (calendar boundaries)
    3. Key VCALENDAR fields are
      1. PRODID: a string describing application vendor and application that generated the ICS file.  The format is -//vendor/product//LANGUAGE
      2. METHOD: a string describing the nature of the ICS/ICAL file.  Common values include PUBLISH (for publishing event information), REQUEST (for requesting an RSVP), CANCEL (for cancelling an event)
      3. VERSION: the version of the ICS/ICAL standard used.  This is commonly just 2.0.
    4. Events lie within calendar boundaries.  The event boundaries are BEGIN:VEVENT and END:VEVENT
    5. Key VEVENT fields are
      1. SUMMARY: a title for your event
      2. DESCRIPTION: descriptive text about your event.  Newlines should be replaced with the literal string “\n”
      3. DTSTART: the start of the event, ideally in UTC
      4. DTEND; the end of the event, ideally in UTC
      5. DTSTAMP: the time the ICS/ICAL file was generated
      6. UID: a unique identifier that can be used to reference the event in subsequent event updates or cancellations.  This can be anything (URL, GUID, SHA-256 hash), but you need to record it, or you’re going to bungle the entire protocol.
      7. ATTENDEE: encoded metadata describing the recipient’s relation to the event. Subfields include…
        1. RSVP: true or false, depending on whether you want the recipient to respond (Google and Outlook will not show RSVP buttons without this)
        2. CN: the name of the recipient
        3. MAILTO: the email address of the recipient
      8. LOCATION: a string describing the location of the event
      9. URL: an absolute URL for the event. Subfields include…
        1. VALUE: the actual URL for the event

    Example ICS/ICAL meeting invite file

    ATTENDEE;RSVP=TRUE;CN=Barack Obama:MAILTO:potus@whitehouse.gov
    SUMMARY:Testing Markdown
    DESCRIPTION:#### Overview\nThis should print as markdown in emails.\n\n###
     # Subtext\nCurabitur cursus purus vestibulum\, venenatis nisi eu\, element
     um tortor. Sed at fringilla dolor\, at aliquam tortor. Morbi interdum lore
     m ipsum\, nec varius est porttitor tempus! Praesent sodales dolor sit amet
      feugiat accumsan. Suspendisse pulvinar convallis orci non semper. Nunc fa
     ucibus scelerisque metus\, vulputate eleifend ligula dictum at.
    LOCATION:no addresses specified
    ORGANIZER;CN=Contoso via My Service Site:MAILTO:guid@reply.servicespark.org

    Attaching a file like this to an outgoing message will cause (most) email clients to display RSVP buttons!

    When an ICS/ICAL file is formed properly, Google will show RSVP buttons.
    When an ICS/ICAL file is formed properly, Google will show RSVP buttons.

    When an RSVP choice is selected, an ICS will be sent as a reply to the endpoint.  The email address that sends the ICS response can not be treated as important, and should not be used to identify the recipient.  For example, Google uses one notification endpoint for all of their users, and you will be unable to reliably determine who is RSVP’ing to the event.   Instead, the UID should be used exclusively, or else updates to the event will cause duplicates, and all other manner of chaos.

    Receiving the RSVP Reply

    When Mandrill receives the reply, they will perform a POST to your specified webhook.  The response will be an ICS file.  The ICS file follows the same format as outlined above: it begins and ends with VCALENDAR boundaries, containing at least one VEVENT inside the VCALENDAR.

    A number of parsers exist for robust ICS parsing, but we are not interested in anything beyond the latest response for the UID.  When the ICS was sent, the UID and the incoming email address were saved.  As a result, we can look up the UID based on the email that it came from.  If an email is received, and there isn’t a valid link between that email and UID, then nothing will be done.

    1. Look up the UID based on email address.  This returns the user, and the corresponding action (event RSVP modification, in this case).  It is worth noting that these email events should expire eventually, so these email endpoints will automatically deactivate.
    2. Regex the incoming ICS response for the VEVENT region containing UID.  This is not a multi-line regex.  This will capture and return the entire VEVENT.
    3. Regex the VEVENT region for a valid going/not going/tentative response.  Please note this is a multi-line regex.  This will check each line and then capture and return the DECLINED, ACCEPTED, OR TENTATIVE state of the RSVP.
    4. Once we have determined the new state of the RSVP, update the user’s RSVP.


    The pieces of this project demonstrate the beauty of event-driven programming.  Using modern web development techniques like webhooks allow for decoupled applications to seamlessly interact with each other.  Mandrill’s service integrates so smoothly with my application that the end result is an interface that is invisible, but robust.  The end result is a incredibly rich interface to an application, where the user interacts and derives value from the application without even logging in.


    Mandrill’s email service does not allow for the appropriate attachment headers (specifically `METHOD: REQUEST`) to be included in the message.  As a result, Outlook (desktop and web) will not show RSVP buttons.  Outlook (iOS and Android) perform according to specification and will present RSVP buttons.

  • I’d better not see that on Facebook.

    I’d better not see that on Facebook.

    Here’s a quote you hear after every camera flash at every party you ever go to.  Or people milling about reminding people to not tag them in photos.

    And why is that, exactly?  So their Mom won’t see?  So that potential employers won’t see what an animal they are?  (employers should never screen prospective employees using Facebook, but that’s a topic for another day)

    The answer is: yes, to all of these questions.  But the reason is simple: people want to be in control of their digital identities.  And that leads me to the thesis: stop putting embarrassing photos of your children online.

    We are pioneers of a new frontier.  We were thrust into a world with social media, but we weren’t given the foresight to see how it will affect our identities months, years, decades, or millennia in the future.  It was a slow fade–we all enjoyed tagging on Facebook, but then what happened?  People lost jobs, or were flatly refused employment as a result of their emerging online identities.  Our consciousness shifted.  We realized that there were consequences to sharing on Facebook.

    It’s time for our consciousness to shift again.

    The next generation is being forced into social media.  Their online identities are becoming known to Google and Facebook, and they don’t even have a say in the matter.  We live in a world where Facebook has facial recognition engines as good as (or better) than the human brain, but infinite capacity to store that data.

    Facebook’s facial recognition is a terrifying collection of data.  This means that a photo you took in a Las Vegas club could actually connect you to the people in the background and margins of your frame.

    We are subjecting our children to this scrutiny.  Our children are not even ready to fathom the expanse of the Internet and how it shapes their identity, yet we are dumping their lives, moments, and history into a machine that knows more about the state of humanity than the world has ever known.

    Our lives are being cataloged.

    Every photo you take is algorithmically scrutinized.  Every post you make is geotagged so you won’t forget where you were.  Every hashtag you use is intimately connected to the breath of global consciousness.

    This is perfectly okay–for you.  Your children do not need their lives pasted into a digital scrapbook they have no control over.

    In the past year, I’ve seen…

    • pictures of naked children in bathtubs (way too many, actually)
    • videos of children crying as they are forced into using a training toilet
    • videos of naked, panicked children running around the house during a rain storm

    And I could go on.  If you’re not comfortable sharing this level of detail about you and your personal life on Facebook (Twitter, Instagram, etc), then you shouldn’t post these things about your children, either.

  • Best Alfredo.

    I’m posting this because this is my favorite recipe.  And also I can never remember where to find it.

    Creamy Alfredo

    I made a tweak the first time I made it replacing the red pepper flakes with cayenne pepper.  I actually prefer it with cayenne.

    Vegetarian.  Quick.  Delicious.

  • Why Is Bitcoin Valuable?

    Bitcoin.  It’s everywhere in the news.  It was 2013’s best investment, and it’s taking the world by storm.

    So why is it a big deal?  And why does it have value?  Well, this is my attempt of explaining one of the fundamental facets of currency: a proof of work.

    Disclaimer: I am no economist.  There are other variables at play when valuing a currency.  Please bring these discrepancies and concerns to my attention in the comments.

    Proof of Work

    Proof of Work is arguably one of the biggest things that make a currency valuable.  The idea is that when we have something, and when we want to use that as currency, we need to know that it wasn’t produced trivially.

    Traditionally, up until recently, we have used gold (or other precious metals) as proof of work.  We understand that gold (etc) is rare, and if someone is able to produce a quantity of gold, we know that they worked a specific, non-trivial amount to obtain that gold.  As a result, our currencies have been defined by precious assets.

    Cool.  But what about Bitcoin?

    Glad you asked!  Bitcoin derives its value from computation.  I.E., Bitcoin is valuable because we use computers to create it.  But how do we create a proof of work out of our computing power?  Easy.  We create problems that take computers a very long time to solve.  In the design of Bitcoin, this is achieved with hashing.

    Okay… What’s hashing?

    According to Wikipedia, hashes are defined as

    [functions] primarily used to generate fixed-length output data that acts as a shortened reference to the original data. This is useful when the original data is too cumbersome to use in its entirety.

    Consider a hash as a boiled-down version of its input.  The hash of a pot of soup would be some sort of reduction scraped off the bottom of a pan.

    What is fascinating about hashes (and this is where the soup analogy stops working) is that hashes are one way.  In most cases, it is impossible to effectively reverse a hash without using trial and error.

    In other words, there is no way to tell what a hash’s input was.

    This is where Bitcoin’s value comes from.

    Hashes and the Blockchain

    Bitcoin transactions are recorded in a special, public data structure called a block chain.  Special programs called miners are used to add new blocks to the end of the block chain.

    A miner’s task is to gather recent transaction metadata and a few other pieces of metadata, and find a random number that, when combined with the rest of the metadata, produces a hash that meets the difficulty requirement of the network.

    For example, a recently mined block has the following hash


    What’s worth note is that this block’s hash has 15 zeroes at the beginning.  This is evidence of the proof of work.  Finding a hash of the block is incredibly difficult right now, and as the Bitcoin network’s computing power increases, the required hashing difficulty increases accordingly.

    How does a computer find a hash?

    1. Gather necessary metadata and structure it according to standard.
    2. Generate a random number and place it in the block.
    3. Hash the block.
      1. If the hash meets the network’s difficulty requirements the block is appended to the block chain, and the next block begins.
      2. If the hash doesn’t meet the network’s requirements, the computer is welcome to try again until it finds a valid hash.

    At the moment, it would take one computer at least 98 years to hash a block by itselfThis is a proof of work.

    Why are hashes good for this?

    Again, good question!  Good hashes are full of entropy.  This is to say that minor changes in the input has a massive effect on the actual output of a hash.

    The following inputs were hashed using MD5.  The passage on the right is missing the period at the end.  Otherwise, the passages are identical.


    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus varius nulla mauris, ac ornare eros venenatis quis. Curabitur elementum risus vitae arcu mollis, vel accumsan nulla tincidunt. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas et condimentum lacus. Maecenas eu nisl ac arcu congue interdum. Sed risus elit, consectetur et venenatis eu, egestas eget nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec a ligula purus. Vestibulum magna ligula, consequat sed varius sit amet, mollis sollicitudin lorem. Nulla et elit neque.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus varius nulla mauris, ac ornare eros venenatis quis. Curabitur elementum risus vitae arcu mollis, vel accumsan nulla tincidunt. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas et condimentum lacus. Maecenas eu nisl ac arcu congue interdum. Sed risus elit, consectetur et venenatis eu, egestas eget nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec a ligula purus. Vestibulum magna ligula, consequat sed varius sit amet, mollis sollicitudin lorem. Nulla et elit neque
    Output (md5) 35f45fa061f48a3d9cfc9ef3dee03aa1 313fb0e8e65bf7ac0a3f16f30f958e17

    What’s interesting is that the hashes are dramatically different.  Consequently, it is nearly impossible to effectively game the inputs of a hash with an understanding of how it will affect the output.

    Interestingly, these two hashes are such rare combinations of letters and numbers that performing a Google search for either hash will probably only lead to this article.

    Most computers with a good graphics card are capable of computing around 30-50 million hashes per second.  That’s 30 to 50 million GUESSES per second.

    The size of the entire network is at 17625 Thash/s.  In other words, the network is guessing 17,625 billion hashes per second attempting.

    Hashes are relatively easy to calculate.  So once a random number is appended to the block and calculated to a valid hash, it can be recalculated instantly and reliability.  This verifies the proof of work.

    The miner that successfully hashes the block is awarded an amount of Bitcoins for their work.  This is how Bitcoins are minted.The first miner to hash the block successfully gets the reward.  As a result, the network races to verify transactions.  Most Bitcoin transactions are committed to the blockchain within 10 minutes!


    This intensive hashing process also makes it virtually impossible to adjust the blockchain retroactively.  If an attacker wanted to undo or alter a transaction that happened in the past, the attacker would have to re-hash the block and every block after it since each block contains the hash of the block before it.  This is too much work for one adversary to achieve in a million lifetimes.

    As a result, once a transaction has been committed to the blockchain, it is safe for eternity.  Bitcoin does not have refunds, or chargebacks for this reason.


    Remember when I stated that one computer would take nearly 98 years to solve a block?  This leads to the exploitation of a very precious resource: our computing power.  At the moment, the Bitcoin network is capable of mining a block in about 10 minutes.

    Mining is most commonly completed in pools that allow participants to solve hashes and share on the minted coins.  You are rewarded in proportion to the amount of work your computer completed.


    Bitcoin is valuable, and we aren’t just pretending like it is for the sake of fantasy.  As with every other valuable currency, there is a proof of work involved in discovering new Bitcoins.

    Rather than physically mining gold or precious metals, the Bitcoin network is seeking an answer (the hash) to a math problem that can only be found by trial and error.  The hash uses transaction metadata and a random number so that any changes in transactions would require rehashing each block of transactions.  As a result, it is impossible to retroactively adjust a transaction.

    Try it!

    Bitcoin is cool.  It makes it easy to send money avoiding restrictions regarding exchange rates and repatriation of money.

    If you are looking to try Bitcoin, head to trybtc.com.  They’ll transfer a tiny amount of Bitcoin to a wallet of your choice.

    Thanks for reading!  If you want to send me Bitcoin for any reason, my public address is 16sVVZiJuCUBpWhKRDse1AzSkNvxHNgceT

  • Fix Mixed-Mode YouTube Embeds in WordPress

    Are you attempting to embed YouTube videos in a secure (https) WordPress site?  Well, browsers should be blocking that content since the videos are not coming in over a secure channel.

    A consequence is that some YouTube videos won’t display, and an error won’t be displayed–which is annoying.

    Here is a brief snippet that can be added to your functions.php file to fix the problem once and for all.

    function youtube_the_content($content) {
    	$search = array("http://www.youtube.com", "http://youtube.com");
    	return str_replace($search, "https://www.youtube.com", $content);
    add_filter( 'the_content', 'youtube_the_content' );

    The line beginning with “$search” specifies that we are searching for non-secure links to YouTube, and the return line combs through the post, and fixes the links so the embeds display properly.  It’s a simple fix, based on WordPress’ powerful filter hook system.

  • Neat Ad

    I’m a huge fan of Lorde’s song “Royals.” This ad features it wonderfully.


  • #vinevortex: Consuming My Life 6 Seconds A Time

    I just thought I should point out, publicly, that Vine is consuming my life.  Vine is the trendy new social network from Twitter that allows you to create and publish short, looping 6-second videos.  The creation controls are primitive, but the results have been extremely creative.

    Your available options for editing include touching the screen to record, and not touching the screen to not record.

    It’s pretty basic, but it’s hopelessly addictive.  iPhone only; for now.


  • Wyoming Wildscapes

    This is one of my favorite videos. You should watch it. Full screen if you can.

  • Brewing Iced Tea Properly

    Picture: Starbucks Black Shaken Iced Tea.  More info at Starbucks’ Website.

    Subtle. Suave. Sophisticated. Our premium black tea gets a snappy little splash of citrus, and then is shaken – not stirred – with ice. We’d tell you more, but the details must remain classified. Still, you do have license to enjoy.

    Tazo® Black Shaken Iced Tea, Starbucks.com

    Bitch, please.  Classified?  Ha!  Iced tea isn’t hard…

    Why the hell am I blogging about this?  Because I see a lot of fools trying to make tea, and they all suck at it.  It’s not hard, but there is a way to do it right to get the crystal-clear, refreshing tea you’re used to seeing/drinking at Starbucks or McAllister’s.

    Black Iced Tea, Proper

    1. Boil 1 liter of water.
    2. Cover 4 cup-sized black tea bags (Lipton will do just fine; Starbucks uses Tazo Awake tea, FYI) with 1 liter of boiling water.
    3. Steep for four minutes.
    4. If you love sweet tea, add 2 cups of sugar to the liter of strongly-brewed tea and stir until dissolved appropriately.* (note: this is how McAllister’s Sweet Tea is made)
    5. Add 1 liter of cold water.  Do not refrigerate.  Refrigeration causes tea to go cloudy.  Cloudy iced tea is bad tea.
    6. Pour a glass as follows
      1. Add equal parts tea and water
      2. Add ice
      3. Shake or stir
    7. Drink that tea.

    I prefer 1/3 tea, water, and ice.  Adjust to suit your tastes.

    EXCITING FISCAL NOTE: this is roughly 12 cents per pitcher and pennies per serving, even if you buy Tazo Brand tea from Starbucks.

    * Never assume that everyone likes black iced tea.  Sweeten your own tea with sugar or simple syrup.