Results tagged “home”

The most up-to-date documentation for Config Assistant can always be found in the plugin, or in source control.

Using Config Assistant for Theme Options

This plugin adds support for a new element in any plugin's config.yaml file called options, which is placed as a descendant to a defined template set. When a user of your plugin applies the corresponding template set then a "Theme Options" menu item will automatically appear in their "Design" menu. They can click that menu item to be taken directly to a page on which they can edit all of their theme's settings.

The static_version root-level element will trigger Config Assistant to copy files to the mt-static/support/plugins/[plugin key]/ folder, and the skip\_static root-level element will let you specify files not to copy.

id: MyPluginID
name: My Plugin
version: 1.0
static_version: 1
template_sets:
    my_awesome_theme:
        base_path: 'templates'
        label: 'My Awesome Theme'
        options:
            fieldsets:
                homepage:
                    label: 'Homepage Options'
                    hint: 'These options only affect the home page.'
                    order: 1
                feed:
                    label: 'Feed Options'
                    order: 2
            feedburner_id:
                type: text
                label: "Feedburner ID"
                hint: "This is the name of your Feedburner feed."
                tag: 'MyPluginFeedburnerID'
                fieldset: feed
            use_feedburner:
                type: checkbox
                label: "Use Feedburner?"
                tag: 'IfFeedburner?'
                fieldset: feed
            posts_for_frontfoor:
                type: text
                label: "Entries on Frontdoor"
                hint: 'The number of entries to show on the front door.'
                tag: 'FrontdoorEntryCount'
                fieldset: homepage
                condition: > 
                  sub { return 1; }
                required: 1
skip_static:
    - index.html
    - readme.txt
    - .psd
    - .zip

Using Config Assistant for Plugin Settings

To use Config Assistant as the rendering and enablement platform for plugin settings, use the same options struct you would for theme options, but use it as a root level element. The static element is also valid here. For example:

id: MyPluginID
name: My Plugin
version: 1.0
schema_version: 1
static_version: 1
options:
  fieldsets:
    homepage:
      label: 'Homepage Options'
    feed:
      label: 'Feed Options'
  feedburner_id:
    type: text
    label: "Feedburner ID"
    hint: "This is the name of your Feedburner feed."
    tag: 'MyPluginFeedburnerID'
    fieldset: feed
skip_static:
    - index.html
    - readme.txt
    - .psd
    - .zip

Using this method for plugin options completely obviates the need for developers to specify the following elements in their plugin's config.yaml files:

  • settings
  • blog_config_template
  • system_config_template

Fieldsets

Fields can be grouped by fieldset, and fieldsets are "tabbed" on the Theme Options screen. This provides an easy way to organize all of your fields and present them to the user in a clear fashion.

options:
    fieldsets:
        homepage:
            label: 'Homepage Options'
            hint: 'These options only affect the home page.'
            order: 1
        feed:
            label: 'Feed Options'
            order: 2

In this example two fieldsets have been defined: homepage and feed, and this will generate two tabs of options on the Theme Options screen. Note that the fieldset keys (in this case homepage and feed) must be unique within your theme or plugin.

Fieldset Properties

  • label - is the description displayed on the tab, and is also displayed at the top of the page.
  • hint - is a space for you to provide more detail about the contents of this fieldset. It is displayed just above all of the fields in this fieldset
  • order - Use integers to sort the order of your fieldsets on the tabbed interface.

Fields

Fields are easily defined with properties.

options:
    feedburner_id:
        type: text
        label: "Feedburner ID"
        hint: "This is the name of your Feedburner feed."
        tag: 'MyPluginFeedburnerID'
        fieldset: feed
    use_feedburner:
        type: checkbox
        label: "Use Feedburner?"
        tag: 'IfFeedburner?'
        fieldset: feed

In this example two options, or fields, have been defined: feedburner_id and use_feedburner. Note that the option keys (in this case feedburner_id and use_feedburner) must be unique within your theme or plugin.

Field Properties

  • type - the type of the field. Supported values are: text, textarea, select, checkbox, blogs
  • label - the label to display to the left of the input element
  • show_label - display the label? (default: yes). This is ideal for checkboxes.
  • hint - the hint text to display below the input element
  • tag - the template tag that will access the value held by the corresponding input element
  • condition - a code reference that will determine if an option is rendered to the screen or not. The handler should return true to show the option, or false to hide it.
  • default - a static value or a code reference which will determine the proper default value for the option
  • fieldset - specify which fieldset a field belongs to.
  • order - the sort order for the field within its fieldset
  • republish - a list of template identifiers (delimited by a comma) that reference templates that should be rebuilt when a theme option changes
  • scope - (for plugin settings only, all theme options are required to be blog specific) determines whether the config option will be rendered at the blog level or system level.
  • required - can be set to 1 to indicate a field as required, necessitating a value.

Supported Field Types

Below is a list of acceptable values for the type parameter for any defined field:

  • text - Produces a simple single line text box.

  • textarea - Produces a multi-line text box. You can specify the rows sibling element to control the size/height of the text box.

  • select - Produces a pull-down menu of arbitrary values. Those values are defined by specifying a sibling element called values which should contain a comma delimited list of values to present in the pull down menu.

  • radio - Produces a set of radio buttons of arbitrary values. Those values are defined by specifying a sibling element called values which should contain a comma delimited list of values to present as radio buttons.

  • checkbox - Produces a single checkbox, ideal for boolean values, or a set of checkboxes. When using this type to display multiple checkboxes, use the values field option to provide a list of checkbox labels/values. Use the delimiter field option to specify how your list of checkbox options are separated. See "Working with Checkboxes."

  • blogs - Produces a pull down menu listing every blog in the system. Warning: this is not advisable for large installations as it can dramatically impact performance (negatively).

  • radio-image - Produces a javascript enabled list of radio buttons where each "button" is an image. Note that this version of the radio type supports a special syntax for the values attribute. See example below.

  • tagged-entries - Produces a pull down menu of entries tagged a certain way. This type supports the following additional attributes: lastn and tag-filter.

  • entry - Produces the ability to select a single entry via a small pop-up dialog. In the dialog, the user will be permitted to search the system via keyword for the entry they are looking for. This field type supports the field property of all_blogs, a boolean value which determines whether the user will be constricted to searching entries in the current blog, or all blogs on the system.

  • page - Operates identically to the entry type except that it pulls up a list of pages in the selected blog (as opposed to entries).

  • category - Produces the ability to select a single category via a drop-down listing.

  • folder - Produces the ability to select a single folder via a drop-down listing.

  • colorpicker - Produces a color wheel pop-up for selecting a color or hex value.

  • link-group - Produces an ordered list of links manually entered by the user. Options of this type will have defined for them an additional template tag to make it easier to loop over the links entered by the user in your templates. See "Link Group Template Tags" below.

  • file - Allows a user to upload a file, which in turn gets converted into an asset. An additional field property is supported for file types: destination which can be used to customize the path/url of the uploaded file. See "Example File" below. Files uploaded are uploaded into a path relative to the mt-static/support directory. Also, for each option of type file that defined, an additional template tag is created for you which gives you access to the asset created for you when the file is uploaded. See "Asset Template Tags" below.

  • separator - Sometimes you will want to divide your options into smaller sections, and the separator facilitates that. This is a special type of field because there is no editable form to interact with and is informational only. Only the label, hint, order, and fieldset keys are valid with this field type.

Link Group Tags

For each option of type link-group that is defined, two template tags are defined. The first is the one specified by the user using the tag parameter associated with the option in the config.yaml. This template tag will be useless to most users as it will return a JSON encoded data structure containing all the links entered by the user.

The second template tag is the useful one. It is called <TAGNAME>Links. This template tag is a container or block tag that loops over each of the links entered by the user. Inside each iteration of the loop the following template variables are defined for you:

  • __first__ True only if the current link is the first one in the list.
  • __last__ - True only if the current link is the last one in the list.
  • link_label - The label associated with the current link.
  • link_url - The URL associated with the current link.

For example, look at this config.yaml:

my_links:
    type: link-group
    label: 'My Favorite Links'
    tag: 'MyFavorites'

This will create two template tags:

  1. <$mt:MyFavorites$>
  2. <mt:MyFavoritesLinks></mt:MyFavoritesLinks>

You can use them like so:

<p>My favorite links are: 
  <mt:MyFavoritesLinks>
    <mt:if name="__first__"><ul></mt:if>
    <li><a href="<$mt:var name="link_url"$>"><$mt:var name="link_label"$></a></li>
    <mt:if name="__last__"></ul></mt:if>
  <mt:Else>
    I have no favorite links.
  </mt:MyFavoritesLinks>
</p>

Asset Template Tags

For each option of type file that is defined, two template tags are defined. The first is the one specified by the user using the tag parameter associated with the option in the config.yaml. This template tag will return the Asset ID of the asset created for you.

The second template tag is <TAGNAME>Asset. This template tag is a container or block tag that adds the uploaded asset to the current context allowing you to use all of the asset related template tags in conjunction with the uploaded file. For example, look at this config.yaml:

my_keyfile:
    type: file
    label: 'My Private Key'
    hint: 'A private key used for signing PayPal buttons.'
    tag: 'PrivatePayPalKey'
    destination: my_theme/%{10}e

This will create two template tags:

  1. <$mt:PrivatePayPalKey$>
  2. <mt:PrivatePayPalKeyAsset></mt:PrivatePayPalKeyAsset>

You can use them like so:

<p>The asset ID of my key file is: <$mt:PrivatePayPalKey$></p>
<p>The URL to my key file is: 
  <mt:PrivatePayPalKeyAsset>
    <$mt:AssetURL$>
  </mt:PrivatePayPalKeyAsset>
</p>

Example File

The file type allows theme admins to upload files via their Theme Options screen. The file, or files, uploaded get imported into the system's asset manager. The path where the uploaded file will be stored can be customized via the destination field option.

Allowable file format tokens:

  • %e - Will generate a random string of characters. The default length of the string is 8, but can be customized using the following syntax, %{n}e where "n" is an integer representing the length of the string.

Example:

my_keyfile:
    type: file
    label: 'My Private Key'
    hint: 'A private key used for signing PayPal buttons.'
    tag: 'PrivatePayPalKey'
    destination: my_theme/%{10}e

Example Radio Image

The radio-image type supports a special syntax for the values attribute. The list of radio button is a comma-delimited list of image/value pairs (delimited by a colon). Got that? The images you reference are all relative to Movable Type's mt-static directory. Confused? I think a sample will make it perfectly clear:

homepage_layout:
    type: radio-image
    label: 'Homepage Layout'
    hint: 'The layout for the homepage of your blog.'
    tag: 'HomepageLayout'
    values: >
      "plugins/Foo/layout-1.png":"Layout 1","plugins/Foo/layout-2.png":"Layout 2"

Working with Checkboxes

The option type of checkbox has two modes:

  • a boolean mode (a single checkbox either on or off)
  • a multi-select mode (multiple choices and options)

A single checkbox is ideal when needing to collect boolean values from users. For example, here is a theme option to enable/disable advertising on a web site:

enable_ads:
  type: checkbox
  label: 'Enable Advertising?'
  hint: 'Check this box if you want advertising to be displayed on your web site'
  tag: 'IfAdsEnabled?'

Your template tag should then be:

<mt:IfAdsEnabled>
   <!-- insert ad javascript -->
</mt:IfAdsEnabled>

Sometimes however you need to use checkboxes to allow the user to select multiple options that all relate to one another. Here is an example of how to use this field to allow users to specify which areas of a site should have ads enabled:

enable_ads:
  type: checkbox
  label: 'Enable Advertising?'
  hint: 'Check this box if you want advertising to be displayed on your web site'
  tag: 'AdsEnabled'
  delimiter: ';'
  values: 'Homepage;System: Profile, Reg, Auth;Entries;Pages'

You can then check to see if the theme option contains a specific value like so:

<mt:AdsEnabledContains value="System: Profile, Reg, Auth">
   <!-- insert ad javascript -->
<mt:else>
   <!-- do nothing? -->
</mt:AdsEnabledContains>

Or you can loop over all the selected values that have been checked:

<ul>
<mt:AdsEnabledLoop>
  <li>You checked <$mt:var name="value"$>.</li>
</mt:AdsEnabledLoop>
</ul>

Defining Custom Field Types

To define your own form field type, you first need to register your type and type handler in your plugin's config.yaml file, like so:

config_types:
  my_custom_type:
    handler: $MyPlugin::MyPlugin::custom_type_hdlr

Then in lib/MyPlugin.pm you would implement your handler. Here is an example handler that outputs the HTML for a HTML pulldown or select menu:

sub custom_type_hdlr {
  my $app = shift;
  my ($field_id, $field, $value) = @_;
  my $out;
  my @values = split(",",$field->{values});
  $out .= "      <ul>\n";
  foreach (@values) {
      $out .= "<li><input type=\"radio\" name=\"$field_id\" value=\"$_\"".
     ($value eq $_ ? " checked=\"checked\"" : "") ." class=\"rb\" />".$_."</li>\n";
  }
  $out .= "      </ul>\n";
  return $out;
}

With these two tasks complete, you can now use your new config type in your template set:

template_sets:
  my_theme:
    label: 'My Theme'
    options:
      layout:
        type: my_custom_type
        values: foo,bar,baz
        label: 'My Setting'
        default: 'bar'

Defining Template Tags

Each plugin configuration field can define a template tag by which a designer or developer can access its value. If a tag name terminates in a question mark then the system will interpret the tag as a conditional block element. Here are two example fields:

feedburner_id:
    type: text
    label: "Feedburner ID"
    hint: "This is the name of your Feedburner feed."
    tag: 'FeedburnerID'
use_feedburner:
    type: checkbox
    label: "Use Feedburner?"
    tag: 'IfFeedburner?'

And here are corresponding template tags that make use of these configuration options:

<mt:IfFeedburner>
  My feedburner id is <$mt:FeedburnerID$>.
<mt:Else>
  Feedburner is disabled!
</mt:IfFeedburner>

Deploying Static Content

Preparing the Static Content

If you've installed many plugins, you know that you must often copy content to [MT Home]/plugins/ and [MT Home]/mt-static/plugins/. For new users this can be a confusing task, and for experienced users it's one more annoying step that has to be done. But no more! Config Assistant can be used to help your plugin or theme copy static content to its permanent home in the mt-static/ folder!

Within your plugin, use the static_version root-level key to cause Config Assistant to work with your static content. This key should be an integer, and should be incremented when you've changed your static content and want it to be re-copied.

If you want to exclude some of your static content from the copy process, you can specify this with the skip_static root-level key, as in the examples.

skip_static:
    - index.html
    - readme.txt
    - .psd
    - .zip

skip_static builds an array of items to be excluded, which is signified with a leading dash and space. Files can be a partial match, so specifying an extension (such as .psd) will cause all files with .psd to not be copied. skip_static is not a required key.

On the filesystem side, you will want to create your folder and file structure inside of a static folder in your plugin envelope. Any files inside of this static folder (except those items matching skip_static) will be copied during installation.

Installing the Static Content

When installing your new plugin or theme, the static_version will trigger Movable Type or Melody to run an upgrade. During the upgrade, Config Assistant will copy static content to the mt-static/support/plugins/ folder, and will create a folder for its contents. (For example, after installing Config Assistant, its static files can be found in mt-static/support/plugins/ConfigAssistant/.)

Note that the mt-static/support/ folder must have adequate permissions to be writable by the web server; Movable Type and Melody will warn you if it does not. Also note that this path is different from where you often install static content, in mt-static/plugins/.

Developers may have reason to reinstall the static content; this can be done by running ./tools/static-copy.

Plugin-Specific Static Template Tags

Two template tags are created for your plugin or theme, to help you type less and keep code clean: [Plugin ID]StaticFilePath and [Plugin ID]StaticWebPath. For example, Config Assistant makes available ConfigAssistantStaticFilePath and ConfigAssistantStaticWebPath.

These tags will output the file path and the URL to a plugin's static content, based on the StaticFilePath and StaticWebPath configuration directives. These tags are really just shortcuts. You could use either of the following to publish a link to the image photo.jpg in your theme, for example:

<mt:StaticWebPath>support/plugins/MyPlugin/images/photo.jpg
<mt:MyPluginStaticWebPath>images/photo.jpg

both of which would output

http://example.com/mt/mt-static/support/plugins/MyPlugin/images/photo.jpg

Callbacks

Config Assistant supports a number of callbacks to give developers the ability to respond to specific change events for options at a theme and plugin level. All of these callbacks are in the options_change callback family.

On Single Option Change

Config Assistant defines a callback which can be triggered when a specific theme option changes value or when any theme option changes value. To register a callback for a specific theme option, you would use the following syntax:

callbacks:
  options_change.option.<option_id>: $MyPlugin::MyPlugin::handler

To register a callback to be triggered when any theme option changes, you would use this syntax:

callbacks:
  options_change.option.*: $MyPlugin::MyPlugin::handler

When the callback is invoked, it will be invoked with the following input parameters:

  • $app - A reference to the MT::App instance currently in-context.
  • $option_hash - A reference to a hash containing the name/value pairs representing this modified theme option in the registry.
  • $old_value - The value of the option prior to being modified.
  • $new_value - The value of the option after being modified.

Example

sub my_handler {
  my ($app, $option, $old, $new) = @_;
  MT->log({ message => "Changing " . $option->label . " from $old to $new." });
}

Note: The callback is invoked after the new value has been inserted into the config hash, but prior to the hash being saved. This gives developers the opportunity to change the value of the config value one last time before being committed to the database.

On Plugin Option Change

Config Assistat has the ability to trigger a callback when any option within a plugin changes. To register a callback of this nature you would use the following syntax:

callbacks:
  options_change.plugin.<plugin_id>: $MyPlugin::MyPlugin::handler

When the callback is invoked, it will be invoked with the following input parameters:

  • $app - A reference to the MT::App instance currently in-context.
  • $plugin - A reference to the plugin object that was changed

Sample config.yaml

id: MyPluginID
name: My Plugin
version: 1.0
schema_version: 1
static_version: 1
blog_config_template: '<mt:PluginConfigForm id="MyPluginID">'
plugin_config:
    MyPluginID:
        fieldset_1:
            label: "This is a label for my fieldset"
            hint: "This is some text to display below my fieldset label"
            feedburner_id:
                type: text
                label: "Feedburner ID"
                hint: "This is the name of your Feedburner feed."
                tag: 'MyPluginFeedburnerID'
skip_static:
    - index.html
    - readme.txt
    - .psd
    - .zip

Our new home

After six long years, numerous rejected offers, and us nearly throwing in the towel on trying to find a home for ourselves in the Bay Area, the Reese family finally purchased a new home. Over the past six years Arin and I have seen a lot of houses, and never, and I do mean never, did we think we imagine ourselves living in a 5 bedroom, 3 bath house that was also in a centrally located neighborhood we love. Yet, as luck would have it, that is exactly where we now live.

I say "luck" because each and every time we would put an offer on a home and subsequently have it rejected I would tell Arin that considering the homes we have traditionally looked at, and the amount we could afford, we would need luck more than anything else in order to have our offers accepted.

Consider for example the last house we bid on. A house we instantly fell in love with. A house that possessed that elusive x-factor necessary for someone to make the single biggest purchase of their lives. We bid close to 10% over asking with an aggressive 21 day escrow and no contingencies. We were as confident as we had ever been, especially considering the state of the real estate market this day and age. But not only were we outbid, but we were outbid by a whopping $100,000 by a couple downsizing into a smaller home.

We. Were. Livid. Heart broken. Dismayed. We lost hope all over again.

Yet, not four weeks later, we were already well on our way relearning one of life's most valuable lessons: everything happens for a reason. Because in that time we found another home, our current one, which was asking a litte bit more, but was more than twice as big. And this time, luck and fate was finally on our side.

We have now been living in our new home for a little less than a week, and I still walk around in a complete state of shock, stealing moments with Arin as we look at each other from across the room mouthing, "oh my god, this is our house!"

Below are pictures I downloaded from the realtor's web site just prior to the listing being removed. I figure they are better than nothing, and certainly better than waiting until Arin and I take pictures of our own.

Now thats Zen

Man watches as house burns down

Bottle of wine in hand and a front row seat, a man watches lava finally consume and burn down his home in Hawaii.

One of the things sadly and remarkably absent from this year's long debate over the push to reform our nation's health care system are the personal stories that help people understand just how important this change is, and the kind of difference it can make to people's lives. So here is a brief perspective on why I am so thankful for tonight's history making legislation.

Most of my life health insurance is something I took for granted. Both of my parents had full time jobs and for my entire childhood, all the way through college I was on one of their plans. Of course, the fact that I had health insurance in the first place never really entered my consciousness, because thankfully I was a pretty healthy kid. The most I saw of our health care system was a yearly visit to the doctor's for a physical and check up.

After I graduated and got a full time job, I continued my march right through my twenties with the same kind of blissful ignorance and lack of appreciation for health insurance. For me, health insurance had always been a given and not something I ever really needed. It was true when I was a kid, and true when I was a healthy 20-something.

In fact, the first time I gave health insurance any thought whatsoever was after I married Arin, when switching to a PPO just seemed like a good idea so that we could both continue to see the doctors we had been seeing, but now under the same plan. But again, all I had to do was check a box on a form, pay a whopping $30 extra per month out of paycheck and presto: health insurance. Truly a beautiful thing.

Fast forward to 2008.

In November of 2008 two things happened. The first was Arin learning that she was pregnant with our second child. Then two weeks later me getting laid off after working at a company I dearly loved for four years.

On the plus side, thanks to COBRA I had the peace of mind knowing that I had a good health insurance plan to cover my wife during her pregnancy and our child's birth. The downside being that our monthly COBRA bill was close to $1500.

If that doesn't sound like a lot of money to you, consider this: $1500 per month was close to 25% of my annual take home pay after taxes, while I was employed.1

My friends were quick to inform me that I was paying too much, that I could get a much better rate if I shopped around. They were of course absolutely correct, however, they did not take into consideration one small snag: my wife was pregnant, and that pregnancy, get this, is considered by insurance companies to be a "pre-existing condition" thank-you-very-much. Meaning, that while I was free to drop our COBRA coverage and switch to a less expensive health insurance option, whichever provider I chose, even if I chose the exact same one, would not cover the costs of Arin's pregnancy and delivery. I was quite simply: screwed.

Unbelievable. Pregnancy. A pre-existing condition. Pregnancy! We are not talking about an illness here. We are not even talking about a chronic condition. We are in fact talking about something that is so natural, and so beautiful that many might argue it is why we were put on this Earth in the first place.

Yet, there you go. Forget the fact that Arin is healthy. Forget the fact that Arin's pregnancy showed no risk signs whatsoever. Forget the fact that Arin's first pregnancy went without a hitch, didn't require costly drugs or pain-killers, and was over and done with in just under three and half hours. No let's ignore the facts and blindly discriminate against a family in their time of need2.

Now, fast forward a year and a half, to the present day. Our nation is poised to pass legislation that will forbid such abusive practices by insurance companies. And while I wish such practices had already been illegal when I was laid off, I rest peacefully knowing that my son and daughter will not live in a country where insurance companies could so openly and cavalierly discriminate against them in a time of need.

1 If you do the math it doesn't take a rocket scientist to learn that I got paid pretty well. So consider for a moment the kind of percentage $1500 per month might equate to for the average middle class American. The thought is simply staggering.

2 Thank goodness our family was not dealing with something more serious and more life threatening. And God, consider those families who are and all of a sidden find themselves without an insurance provider they can switch to.

I have a love/hate relationship with Amazon right now as they recently made changes to their Amazon Product Advertising API that has broken Media Manager. Now I have numerous users tapping their feet anxiously waiting for an update, during a time in which I really should be working. I have only myself to blame though as Amazon gave me more than enough warning of this change, emailed me numerous times warning me about it, and honestly did all that a services provider should do to inform me of this impending change and its consequences. But naturally I procrastinated, and now I must reap what I sow.

On the flip side, this change has forced me to crack open one of my oldest plugins, one built with a great deal of duct tape and chicken wire, and retool it to be slightly more modern. Most users of course won't appreciate or notice a change, but I myself am relieved to finally replace all of my home-grown web services code, with a more stable and tested equivalent. This hopefully will make it easier for me to add features in the future and not cringe quite as much whenever a user reports a bug.

So while I privately curse Amazon under my breath, Media Manager and Movable Type users can thank Amazon for forcing me to finally devote some time to this plugin.

And that's the good news: Media Manager is getting a much needed overhaul: it is being updated to work with Amazon's new API restoring its operability; and I am making this work available for download today. The bad news is that this work is not 100% complete, so I must beg the for the community's continued patience and understanding in that this overhaul will take a little more time to complete. In the meantime, those willing to experiment with something that is partially complete, you can download and follow my progress with Media Manager over at github, and you can report bugs via the web and email over at Lighthouse.

Daisy Amelia Hailey Reese

In a way I am never to forget, our newest addition, Daisy Amelia Hailey Reese, was brought into the world at 5:16am on June 26, 2009. She was 7lbs, 10oz and 20.5 inches long. Labor was a mere 45 minutes long from start to finish.

Twitter - something is coming out

For the full story of her, keep reading.

Meet Melody

People who know me, know that I love Movable Type. In fact I have devoted much of the last five years to the product and its community. Therefore it gives me great pride and much relief to be a part of the launch of Melody, a new community-driven content management and blogging platform based upon Movable Type.

melody-logo-on-white.jpg

I have written extensively about what motivated me and others to create this project so I won't bother recapitulating that here.

What is likely to get lost today in whatever attention this humble project is likely to attract is any mention of the people who have helped take this project this far. Without the dedication of these people over the past six years Movable Type would be a fundamentally different product than it is today, and Melody might never have happened. So I would like to carve out a little space to say thank you to the following contributors to Melody and my friends:

  • Jay Allen - While I have been remiss in mentioning it here, Jay and I are now partners in what is becoming a very successful Movable Type (and now Melody) consulting business. For Melody Jay has been playing the role of lead developer by helping manage code merges with Movable Type, organizing our source code and writing all of our developer contribution guidelines.

  • Jesse Gardner - I have worked with Jesse for years. It was a pleasure to work with him on the design of Movable Type [dot org] and an even greater privilege to work with him on what I think is a damn fine looking web site and the home for our new community: OpenMelody.org.

  • Tim Appnel - Tim has been a dutiful project manager as well as our system administrator taking on the unglamorous and thankless task of setting up servers, managing ACLs, and all the other stuff that makes the bits and bytes flow as God intended.

  • Dan Wolfgang - Dan built out our web site, and has been first in line to take stuff off of people's plates when they become too full. Never under-estimate the value of load balancing people. Seriously.

  • Mark Stosberg - Mark's invaluable experience in serving on the boards of several non-profits has helped us greatly in our process of writing our own by-laws for the Open Melody Software Group. He is also our unofficial ambassador to the greater Perl community in CPAN, where he helps to maintain a number of modules.

  • Su - I have never known Su to be one who likes the lime light, so I will simply say this: he has been a consistent and reliable voice of reason within our group, which is essential when dealing with so many people who are as passionate as we are.

  • Arvind Satyanarayn - The famous Movable Type prodigy-kid and author of Custom Fields took a break from college girls and parties to help contribute much needed code and infrastructure that will undoubtedly become essential to the project. He also surprised us all by merging all of Movable Type 4.261 into the latest development branch of Melody - hoooo-aaaah!

Finally, I would like to thank Six Apart. There is no doubt that many people will want to spin this initiative by the community in a way that impugns the company and the many people who work there and whom I call a friend. There is no way around the simple and basic truth: without them, this project would not exist and without their support of the project, I doubt it could reach its fullest potential.

And after all is said and done, this is what Melody is all about: these people, our community, and the many people who will follow. Thank you!

My kid turned three this week. Three. One, two, three. It blows my mind every time I say it.

Harper blowing out a candle

Harper blowing out his birthday candle on his birthday cupcake. He ate it so fast he threw up. That's love my friends, love.

Marking this wonderful day is a reminder of how much faster time goes by not just as an adult, but as an adult with kids. I cringe something as cliché as this, but it seems like yesterday that we brought home from the hospital.

Last week Arin and I noticed on our way to the Farmer's market that a small group of bees were loitering about the roof of our porch. We didn't think much of it and resolved that we would check with our neighbor to see if she might want to come over and harvest them to add to her own hive which she maintains in her backyard. Our neighbor liked the idea, so we decided that later in the day when most of the bees were likely to be off foraging away from the hive that we would get together to help facilitate the move.

Around 4pm that day I heard her calling me. I was in my backyard gardening and figured that it was time for us to deal with our little bee project.

It was then that I looked up and saw, two doors down from my own, a relatively impressive cloud undulating in the air over my neighbor's backyard. Esperanza was in my backyard moments later and I asked, "are those your bees?" To which she responded, "yeah; this is not good."

Bee Swarm above Roof

Pictured above you can see the swarm in the air and bottlenecked trying to get all who-knows-how-many-thousands of themselves in the roof space above my porch through a 1/2 inch hole.

What we were witnessing was a swarm of bees, about half of her hive, in the process of up and moving itself to the roof above my porch. The small number of bees I had noticed in the morning could best be described as part of the advance team that was helping to prepare the hive for the move. Then, at around 4pm, the queen decided that it was time to move. So she did – and where she goes, the hive goes. All at once.

To say that there were a lot of bees would be an understatement, but at the time it was hard to fathom as they swarmed around me standing in my front yard. I suppose it would be as if you were floating in the middle of a cloud in the sky and I asked you, "how big is that cloud you are in?" A difficult question to answer unless you were standing outside the cloud and had some solid point of reference.

From Esperanza's blog:

[Byrne] is not accustomed to bees and so he ever so calmly said "I am alarmed." I did my best to talk him through it, "the bees are at their least defensive state;" "they are full of honey and docile when they swarm." "They just want to find their queen." He said "there are hundreds and hundreds of them." I did not bother to correct him to say "no, Byrne, there are actually thousands."

Esperanza tells the whole saga on her blog, but long-story-short, there is now a significant hole in my roof, the queen was saved, the colony has been safely moved to a new home and I am proud that I can say that we did all that we could not to contribute to the rapid decline of the global and national honeybee population.

I recently read that Jacques Littlefield, a person whose collection I irrationally envy, and whose obsession I strangely understand, lost a battle to cancer at the age of 59. What did he collect?

What else: tanks. To which he devoted a football field sized "garage" to.

Jacques Littlefield

His collection housed tanks and other self-propelled means of destruction from virtually every country that ever made a tank, and from ever war in which tanks were used. His collection is the largest private collection of military vehicles and is considered one of the best if not the most comprehensive, and even rivals the largest military museums in the world. His most recent acquisition was a German Panther tank that rested at the bottom of a river ever since the end of World War II. There are only 28 known Panthers still in existence today in any condition whatsoever. His will be number 29.

One day I can see taking Harper to go see his collection housed at the Military Vehicle Technology Foundation, which he founded in 1998. Assuming of course if it is ever opened to the public (crossing fingers).

If the old and cheesy poster I remember from the 80s that reads "the person who dies with most toys, wins," is even slightly true, then Jacques Littlefield wins. By a mile.

Photo courtesy of SFGate

See also:

Delia and Harper

Harper had so much fun with cousin Delia this week in Austin. Word has it that Delia is already upset that Harper will soon be going to the airport, and I anticipate that when we return home Harper will be confused why he can't just hop over and see Delia anymore.

Seeing these two together is something special: whenever they see each other you can witness enthusiasm and joy building and building until they both explode in a fit of laughing, jumping up and down and stomping their feet.

Here is something I never thought I would ever hear myself say, "I love my plumber."

At the risk of revealing just as bourgeois as I am, I will say this: after living in Oakland for the past 12 years I must admit how hard it is to find good help these days. I could regale you with stories about gardeners who are completely unable to work without using some ear splitting gas-powered device, general contractors who have a case a beer during the course of the day (not to mention leaving it behind for you to clean up), contractors who "accidentally" drill holes into the side of your house, cablemen who steal stuff out of your basement, etc. The list goes on.

So when I put the call out to my friends to recommend a plumber I expected at best to get a bunch of, "this person's not bad" and "this person has never screwed up." Or in other words a battery of half-recommendations, and no sincere endorsements.

But my friend Cynthia (who has a great blog on Vox), left a response that caught my eye. She referred me to Michael Your Plumber.

My experience with him was nothing short of awesome. He came to my home, on time, and not only worked to solve my problem, but also showed me exactly what he was doing in an honest attempt to show me just how easy this stuff can be. He even left behind spare parts in case I ever wanted to do tune ups again on my own. He was nice, professional, and actually kind of fun to have in my home.

As he was wrapping up however, I braced myself expecting the fairy tale to come to an abrupt end as he told me how much I would owe him. But alas, he rate was beyond reasonable - it was down right generous. I wrote my check, we chatted some more and he was off. Amazing.

But the story does not end there. This week I got a postcard in the mail. Guess who it was from? Michael Your Plumber. He was thanking me.

plumber-postcard.jpg

I am willing to bet that none of you have ever gotten a postcard from your plumber. That is because they are not Michael.

I don't how to say this any other way, but Michael is flat out awesome and is the best contractor I have ever worked with. So, if you live in the Bay Area -- Oakland, Berkeley and the East Bay especially, I cannot recommend him more. He is the best plumber around.

Michael Your Plumber: (510) 472-0123.

A long time ago I hacked together one of my first PHP Projects called the Fantasy Book List. This project's aim was to make one of the best book lists I had stumbled upon at the time into a more browser friendly web site.

The book list however is no longer being maintained and I have discontinued this project. Happily though, others have stepped up to help maintain the project.

For those looking for an excellent Science Fiction or Fantasy Book to read, let me recommend one of the following:

My Favorite Fantasy and Science Fiction Books

The Lord of the Rings Dune, 40th Anniversary Edition (Dune Chronicles, Book 1) Ender's Game (Ender, Book 1) Stranger in a Strange Land A Game of Thrones (A Song of Ice and Fire, Book 1) The Mists of Avalon

Podcasting support for Movable Type just got better. In this most recent release of the Podcasting plugin for Movable Type, iTunes support has been rounded making it easier than ever before to get your podcast listed and listed properly within the iTunes Music Store. This latest release adds the following features:

  • a complete RSS feed that includes all of the proper iTunes meta data.
  • an enhanced submission form that collects addition information about your podcast including its duration, whether it contains explicit material, a subtitle, summary, keywords and more.
  • additional plugin options to capture important information about your blog so that its listing within iTunes can be finely tuned.
  • support for basic authentication to access podcasts located behind a username and password.
  • enhanced error messaging when linking to feeds.

This release is a necessary and important step to help make Movable Type the premiere self-hosted podcasting platform on the planet. I am excited by this release and am growing even more excited about the next one, which may include any number of the following features:

  • download statistics for your podcasts
  • iTunes notification pings
  • auto-podcast submission to iTunes

But this plugin has been more the result of the feedback I have heard from folks like Bud Gibson, Todd Cochrane and others. So I anxiously await hearing from the Movable Type user community what they would like to see in the next version.

Clean Sweep Updates

Clean Sweep Dashboard Widget

A while ago I switched from Apache to Lighttpd and in the process I broke my very own plugin installed locally here on majordojo: Clean Sweep. Clean Sweep is a plugin designed to help put an end to 404's on your blog that result in a lowered page rank, a poor reader experience, and poor performance overall.

In this latest release I have:

  • fixed a few bugs.
  • added support for Lighttpd making configuration as easy for this light weight web server as it is for Apache based web servers.

You may download the update from Clean Sweep's home page.

This year for my birthday, Harper hit a home run when he purchased one of the coolest pop-up books I have ever laid my eyes on. The thickness of the book as a ratio to the number of pages I think says it all:

2 pages per inch

The book though is unique in that it isn't just 3D, it is practically 4D with layers upon layers of hidden details. Some obvious, and some not so obvious. Take for example the last page of the book in which Darth Vader's mask emerges from the pages in a spectacular display of paper architecture and engineering.

Darth Pop Up

But what is most interesting about this particular page is not the mask, but what is inside the mask.

Anakin Pop Up

And that is just one page. A page in fact that has four other pages that can fold out and pop-up in addition. Like this mini-page:

darth3.jpg

By the way, if you are wondering if that lightsaber is glowing... yes it is.

If you are interested in buying the book for yourself or a Star Wars obsessed loved one like me, you can buy it from Amazon.

Star Wars: A Pop-Up Guide to the Galaxy

Google gets it wrong Over two years ago when Google Maps released their satellite maps feature and the rest of the world was ooooh'ing and aaaaaah'ing, I wrote a post saying Google Maps sucked because when I typed in my address, they couldn't pinpoint my exact location. Pshaw.

I was being facetious. I am a Google Maps fan-boy like everyone else - except of course when you ask for directions and its sends you to the wrong city. But that is a whole other blog post.

Today I found out that Google now lets users edit maps. The first thing I did was adjust where Google things my home is. Now when you type in my address - you get the exact point on the map.

I may be the only person in the world that cares that Google gets this right, but I must admit, it is a cool feature nonetheless.

Google Maps circa 2007

Regarding Enclosures

Excellent and detailed analysis of Movable Type's support for podcasting and enclosures. Movable Type can definitely improve - there is no doubt - but it is good to see some root cause analysis of Geek News Central's issues posted about previously.

Tags: , , ,

Can you prove a murder without a body?

Are you serious?! Hans Reiser will be tried without ever having found the body of the person he allegedly murdered? Will this honestly be a hard defense? "Ladies and Gentlemen of the jury, my client might have killed the victim. But then again, she might also be alive. Is it reasonable for anyone to think that she *might* be alive?" Or whatever. But come on.

Tags: , ,

Plant Gel vs Ant Gel

Tags: , , ,

A Home from the Solar Decathlon

The home focused on the concept of passive energy and was designed essentially as a box with three layers - an outer layer of oak, louvered screens that generate electricity with photovoltaic energy, a middle layer consisting of energy efficient walls and windows, and an interior core that houses the kitchen, bathroom and the majority of the building systems.

Tags: , , , ,

Tim O'Reillly on "Mark Cuban, Facebook, and OpenSocial"

"I think Amazon is the only company that really understands that we're in the process of building an internet operating system, and is building services with the depth and power that will be required to create the next generation of computer applications. [snip] (I take that back. I think Six Apart gets it.)"

Tags: ,

LEGO Indiana Jones

Please be released to OS X. Please be released to OS X. Please be released to OS X. Please be released to OS X.

Tags:

Details On The Open Source Version Of Movable Type | Compiler from Wired.com

Wired is starting to piece together a lot of different details about MTOS...

Tags: , ,

US House Resolution 333

Rarely does a house bill get me so excited.

Tags: , ,

View all my bookmarks on Ma.gnolia

So yesterday was a day just like any other day, except that I had the pleasure of listening to a Movable Type user rant about our claimed, but "lacking" support for podcasting. Man, it hurts hearing such a passionate user become so frustrated.

But it is precisely at times like those that we at Six Apart swallow our pride and listen to our users. Not hear them. But actually listen to them.

And you know what, Todd is right about at least one thing: Movable Type's support for podcasting could be better. A lot better. So I went ahead and slapped together the first Podcasting Plugin for Movable Type 4.0, and I call upon Todd (and the rest of the Movable Type user community) to help me make this the best podcasting plugin for any blogging product.

Now I put together this first pass really quickly - in just a couple of hours actually, which I think is a testament to how easy it is to build a plugin on Movable Type for anyone who knows a little Perl, not to mention evidence to what it means to be a true Media Platform (see also the YouTube, Flickr and Amazon asset integration provided by Media Manager).

But I digress. I purposefully put together the most minimal feature set possible and still meet Todd's basic requirement: the ability to link to an externally hosted MP3 file and have Movable Type encode the necessary enclosures within an RSS and/or Atom feed. For fun I am redistributing a free flash MP3 player licensed under the creative commons to make it easy for users to allow readers to listen to their MP3 files directly from their blog.

But now I need to pass the baton to Todd, ProNet (especially Budd) and any other serious podcaster (Niall?) to help me shape the remaining feature set for this plugin. As a Product Manager myself I am reasonably certain think I could define a feature set myself, despite how clueless Todd may think I am, but I really do want this plugin to be something informed directly by the community. So please, everyone, chime in.

Todd, I am personally sorry you had a hard time with Movable Type. I sincerely hope this plugin will begin to provide the functionality you need, and I hope we can continue to evolve its feature set together as a team.

Mint: a review

Mint Logo

About five years ago I abandoned the last of my brick-and-mortar financial institutions so that I could manage my money exclusively online. I left Bank of America in favor of eTrade because I believed that as a modern Internet company eTrade stood a much better chance of developing the kind of banking application I would not only value, but also have a modern and savvy user interface. So I switched everything over and bought Quicken, with a rare enthusiasm and excitement for I believed that this would be the new dawn of a new me, a me that actually had his finances ordered and up to date at all times.

Imagine my surprise when I booted up Quicken only to find that it was incompatible with eTrade Bank. Believe it or not, that was in 2003. Three years later when my wife and I began to contemplate buying a new home and I had a renewed interest in trying to gain greater insight into how my wife and I spend money. So I decided to check back with Quicken and see if they had yet added support for eTrade Bank. They had not.

"Shock" does not even begin to describe the feeling I had. I had chosen eTrade because I believed that a company that existed almost exclusively online would work best with products like Quicken that wished to synchronize users' data with financial institutions over the Internet. Seems like a reasonable conclusion to reach, right? Um, yeah.

So in an effort to get a handle on my family's finances I turned to the oldest personal financial application around: Excel. I imported what I could from eTrade and then began the process of manually categorizing all of my income and expenditures over the past three months. It was excruciating and. mind-numbing. But it was also very error prone because my categorization scheme kept adapting and changing as I began to understand my own expenses more and more. During the whole process I kept asking myself, "can't Quicken do this for me? Don't they have enough people's data to know how people generally categorize a payment to Amazon or Grand Lake Theater?"

In the end I toiled over that spreadsheet for about 3-4 hours knowing full well that if I ever needed to update my finances I would need to do it all over again. Talk about poking yourself in the eye with a stick.

I had resigned myself to never finding a tool that would work for me. But just the other day, I stumbled upon a newly released product that in an almost clairvoyant fashion did exactly what I was trying to achieve in Excel in a little under 5 minutes. Plus it gave me the simple, easy to understand personal finance analytics I wanted out of Quicken, and it did it all for free.

So, yes, I am a fan of Mint. I will admit. But it is not perfect. It does a lot of things right, which I talk about below, but there are many things I would like to see it do differently.

Turning Personal Finance into a Game

debt-equity.png

A number of notable product design folk talk about the use of game mechanics within the tools we use to help fuel our use of and addiction to them. These same game mechanics can also be used to turn otherwise mundane or even anxiety-ridden tasks into ones that are actually and quite possibly fun. The "game" Mint offers lies in encouraging the user to take actions in their personal life in order to manipulate Mint in respondiing in a favorable and desired way. One very simple example of how Mint does this already is with the widget that shows a user's ratio of equity to debt. This is an incredibly reductionist view of your finances, granted, but that is the beauty because it is easy for me to understand how to move the bar left and right. Another good example is the "how do you compare" feature which actually pits me against others users in the system. This I love because it taps into my competitive nature. I hate know for example that I pay more then most others for gas, especially consider how little my wife and I drive.

compare.png

Mint is only scratching the surface here. The truth is that Mint has lots of fertile ground to help provide additional feedback to the user to help encourage them to develop discipline around their finances, and I hope that Mint begins to define its more of its features with game mechanics specifically in mind. I just love the idea of an application I use enticing me to be better about finances - either overtly or subconsciously. I don't care, because the end result is a real value to me no matter what.

The Brilliance Behind the Product

Omniture and then Google showed the world that advertising can be actually be perceived as valuable by users when that advertising is actually relevant to the content of the page and provides some kind of value to the user. It is my belief that search remains the only context for advertising where the ad serves a purpose and value relatively equal to the content itself. Sure, content targeted advertising on blogs can be relevant, but they are still widely recognized as "ads" in the most pejorative sense of the word, and not immediately perceived as a value.

save-money.png

Mint may very well have discovered the next form of ad unit that provides what consumers will widely perceive as truly valuable. Just click on the "Ways to Save" and you are immediately taken to a page that shows me products and services that will potentially save me money. For example, Mint knows what credit cards I have and their interest rate, so it can present me with credit cards to transfer my balance that will save me on interest payments. Mint also knows who my cell phone provider and can present me with alternative cell phone providers that can save me money on my monthly payment. I honestly hope that one day Mint will also:

  • Help me find a better longer term mortgage. What I hope Mint does not do is help me lower my monthly payment. That is a crock. I want Mint to help me build equity in my home, not help others leach equity from it.
  • Offer vacation packages for me based upon the cities it sees me spend money. For example, Mint should know that I visit Los Angeles from time to time, and should be able to offer ways to save on my next trip there.
  • Help me find a better place to save my money by recommending CDs or Mutual Funds based upon how much of my equity is liquid on average.

A Few Recommendations for Mint

  • Make Community More Apparent - The "How do you Compare" feature is awesome, but I think there is greater potential to inform how users can more actively contribute to the system and one another. It would be great to actually show information about each transaction on how others have categorized an item. I am certain their must be something at work on the backend taking into account how others are training the system, but surfacing that information I think will help encourage that behavior in users even more.

  • Allow for Category Suggestions - I actually like the constraints you place around categories. While I think a compelling argument can be made to allow people to create their own ontology, I think it is wiser to constrain users, lest they over complicate something that Mint is trying to keep simple. But man, I sure would like a few changes made... perhaps you could let users suggest categories? For example, I would love a category for Home Business (both income and expense). Oh, and I want a "Delivery" option under Food because one thing I am dying to know about myself is how often I "order out."

  • Encourage me to Categorize - I think categorization is one of the most important activities a user can engage in. There should be some kind of statistic on the dashboard widget that shows how many uncategorized items I may have. When I click it I should be taken to a "to do list" of sorts that shows all of the uncategorized transactions in my account. As I assign each to a category, my to do list gets smaller and smaller. Ultimately I should categorize very infrequently because over time I should be training the system to do it for me.

  • "Labels?" Come on, they're tags. - I wish a more conventional method for applying labels, or let's be honest with one another, tags to my transactions. I would be more diligent about tagging my transactions if the process was more fluid and less cumbersome. Go for a tagging interaction model like Flickr or Vox.

  • Spending Trends Improvements - The pie chart is nice, but it is not 66%-of-the-screen-nice. Some of the stats I am really interested in are the less prominent stats, like who are my "favorite" merchants, especially over time. I also want to gain a better understanding of income as well and the ebb and flow of income to expense. Let me blow up spending charts... I want to see more than the top 3 places I spend money within any given category.

2 3  


Recent Comments

  • Seth, we have identified several reasons why duplicate transaction may occur. These cases should be addressed early next week and your dups should be removed automatically. If they persist, please contact us again and ...

    Aaron Forth, VP of Product, Mint.com
    Mint: a review
  • Have you noticed lots of transactions getting duplicated in your Mint data? It's very annoying. I submitted a bug about it but haven't heard back in about a week and a half (after getting a human reply in about 10 minu...

  • I third the nice review part. I'm heavily ingesting the Mint Kool-Aid but I would like to add my things I'd like to see (since you've gotten the Founders attention): A way to export my transactions. Partnership with a...

  • Byrne, Great review. My VP of Product pointed me to this as one of the most insightful reviews he's read. Of all the blogs and press we've received, you alone (so far) realize that Mint "ads" are revolutionary - users...

    Aaron Patzer
    Mint: a review
  • Thanks for the thoughtful review and the product suggestions. Several of the product suggestions that you have written about are in progress. Looking forward to getting your perspective as soon as they are live! Thank...

    Aaron (Mint Product Management)
    Mint: a review
Close