SlideShare a Scribd company logo
1 of 51
Download to read offline
PLUGINS ARE
   BLUEPRINTS
Decoding the presentation,
behavior and structure of
WordPress plugins to make
them your own




WordCamp Boston 2011
Marc Lavallee, @lavallee
Wesley Lindamood, @lindamood   Credit: Chris Ware- Building Stories
PLUGINS ARE
   BLUEPRINTS
Decoding the presentation,
behavior and structure of
WordPress plugins to make
them your own




WordCamp Boston 2011
Marc Lavallee, @lavallee
Wesley Lindamood, @lindamood   Credit: Chris Ware- Building Stories
CONFUSION
COHERENCE




            Credit: David Arpi/Flickr
DECODING A PLUGIN                        http://bit.ly/pKLC7I




                    Credit: Bob Baxley
PLUGIN USAGE



     USE                  PATCH                                       BUILD

 • W3 Total Cache
 • Google Analyticator   • FD Feedburner   • Slides for WordPress     • Embed.ly       • Link Roundup




       Use                    Patch          Prototype and          Draw inspiration     Start from
      as-is                                    customize                                  scratch
PLUGIN USAGE



     USE                  PATCH                                       BUILD

 • W3 Total Cache
 • Google Analyticator   • FD Feedburner   • Slides for WordPress     • Embed.ly       • Link Roundup




       Use                    Patch          Prototype and          Draw inspiration     Start from
      as-is                                    customize                                  scratch
CUSTOMIZING PLUGINS


1   Find the best available plugin


2   Explore through prototyping


3   Decide to build or patch


4   Begin development
AN EDUCATED GUESS

                               PRESENTATION



                          BEHAVIOR




              STRUCTURE
WHEN TO USE A PLUGIN

                                         PRESENTATION
                 USE
                                 BEHAVIOR




                  STRUCTURE




         Small    AMOUNT OF PLUGIN CUSTOMIZATION   Large
WHEN TO PATCH A PLUGIN

                                         PRESENTATION
                 USE
                                 BEHAVIOR
                 PATCH
                  STRUCTURE




         Small    AMOUNT OF PLUGIN CUSTOMIZATION   Large
WHEN TO BUILD YOUR OWN PLUGIN

                                         PRESENTATION
                 USE
                                 BEHAVIOR
                 PATCH
                  STRUCTURE


                 BUILD


         Small    AMOUNT OF PLUGIN CUSTOMIZATION   Large
Example One
NAVIS SLIDESHOWS
A LIVING PATTERN LIBRARY




            Credit: Mark Killingsworth




I start where
the last man
left off
— Thomas Edison
OUR STARTING POINT            http://bit.ly/gKHLvt




       Slides for WordPress
WORDPRESS DEFAULT
A PLUGIN JUMPSTART
A FUNCTIONAL PROTOTYPE
CONDITIONAL IMAGE LOADING                                                   http://bit.ly/pab-images

ELEMENT BEFORE
<div id="7118-slide3" data-src="http://e.opb.org/files/2011/07/3.jpg*450*600" />


ELEMENT AFTER
<div id="7118-slide2"><img src="http://e.opb.org/files/2011/07/3.jpg" width="620" height="465" />


JAVASCRIPT
function ensureImageIsLoaded( postID, slideNum ) {
    var slideDiv = jQuery( "#" + getSlideElement( postID, slideNum ) );

    // Do nothing if the slide image already exists
    if ( slideDiv.has( "img" ).length )
        return;

    var imgData = slideDiv.attr( "data-src" );
    if ( imgData ) {
        var parts = imgData.split( "*" );
        var img = jQuery( "<img/>" )
            .attr( "src", parts[0] )
            .attr( "width", parts[1] )
            .attr( "height", parts[2] );
        slideDiv.prepend( img );
    }
}
CONDITIONAL SCRIPT LOADING                          http://bit.ly/pab-scripts

<?php
$argo_include_slideshow_deps = false;
add_filter( 'post_gallery', 'argo_handle_slideshow', 10, 2 );
add_filter( 'wp_footer', 'argo_add_slideshow_deps' );

function argo_handle_slideshow( $output, $attr ) {
    global $argo_include_slideshow_deps;
    $argo_include_slideshow_deps = true;
    return do_other_slideshow_things( $output, $attr );
}

function argo_add_slideshow_deps() {
    global $argo_include_slideshow_deps;
    if ( ! $argo_include_slideshow_deps ) { return; }

    // jQuery slides plugin from http://slidesjs.com/
    $slides_src = plugins_url( 'js/slides.min.jquery.js',
__FILE__ );
    wp_register_script( 'jquery-slides', $slides_src, array
( 'jquery' ), '1.1.7', true );
    wp_print_scripts( 'jquery-slides' );
}
?>
PLUGIN SEDIMENT

SLIDES FOR WORDPRESS
 PHP: 39k
 895 lines
 748 sloc

NAVIS SLIDESHOWS
 PHP: 8k
 244 lines
 199 sloc
WHAT WE CHANGED

    STRUCTURE                                                                            PRESENTATION
•   Remove unneeded options and features

    BEHAVIOR
•   Conditionally load slideshow CSS, JS                                          BEHAVIOR
•   Dynamically load images

•   Add custom taxonomy for sideshow content type

•   Add image permalinks
                                                                   STRUCTURE

    PRESENTATION
•   Add credit and caption

•   Adjust placement of UI controls, the width of images
    and look and feel of the slideshow to conform to
    Argo standards.

                                                           Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                               USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                            PRESENTATION
•   Remove unneeded options and features

    BEHAVIOR
•   Conditionally load slideshow CSS, JS                                          BEHAVIOR
•   Dynamically load images

•   Add custom taxonomy for sideshow content type

•   Add image permalinks
                                                                   STRUCTURE

    PRESENTATION
•   Add credit and caption

•   Adjust placement of UI controls, the width of images
    and look and feel of the slideshow to conform to
    Argo standards.

                                                           Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                               USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                            PRESENTATION
•   Remove unneeded options and features

    BEHAVIOR
•   Conditionally load slideshow CSS, JS                                          BEHAVIOR
•   Dynamically load images

•   Add custom taxonomy for sideshow content type

•   Add image permalinks
                                                                   STRUCTURE

    PRESENTATION
•   Add credit and caption

•   Adjust placement of UI controls, the width of images
    and look and feel of the slideshow to conform to
    Argo standards.

                                                           Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                               USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                            PRESENTATION
•   Remove unneeded options and features

    BEHAVIOR
•   Conditionally load slideshow CSS, JS                                          BEHAVIOR
•   Dynamically load images

•   Add custom taxonomy for sideshow content type

•   Add image permalinks
                                                                   STRUCTURE

    PRESENTATION
•   Add credit and caption

•   Adjust placement of UI controls, the width of images
    and look and feel of the slideshow to conform to
    Argo standards.

                                                           Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                               USE         PATCH       BUILD
Example Two
RSS & EMAIL
OUR STARTING POINT               http://bit.ly/gbx4j2




                 FD Feedburner
EMAIL SUBSCRIPTION INTERFACE
MENU PLACEMENT
<?php
// In our theme's functions.php file
if ( function_exists( 'feedburner_config_page' ) ) {
    add_submenu_page( 'plugins.php','Feedburner Configuration', 'Feedburner
Configuration',
        'manage_options', 'argo_feedburner_menu', 'feedburner_conf' );
    remove_submenu_page( 'plugins.php', 'fdfeedburner.php' );
}
?>
USER AGENT CUSTOMIZATIONS
<?php
// In FD Feedburner plugin
function feedburner_redirect() {
    global $feed, $withcomments, $wp, $wpdb, $wp_version, $wp_db_version;

    do_a_bunch_of_stuff();

    // Do nothing if not a feed
    if (!is_feed()) return;

    $skip_useragents = array( '/feedburner/i', '/googlebot/i' );
    $skip_useragents = apply_filters( 'feedburner_skip_useragents', $skip_useragents );
    foreach ( $skip_useragents as $ua ) {
        if ( preg_match( $ua, $_SERVER[ 'HTTP_USER_AGENT' ] ) ) return;
    }

    do_more_stuff();
}
?>
<?php
// In our theme
add_filter( 'feedburner_skip_useragents', 'argo_allow_yahoo_pipes' );

function argo_allow_yahoo_pipes( $useragents ) {
    $useragents[] = '/yahoo pipes/i';
    return $useragents;
}
?>
WHAT WE CHANGED

    STRUCTURE                                                                      PRESENTATION
•   No changes

    BEHAVIOR
•   Change user agent list                                                  BEHAVIOR
•   Add an email subscription form into the footer

•   Create an email subscription widget

    PRESENTATION                                             STRUCTURE
•   Widget and footer styling




                                                     Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                         USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                      PRESENTATION
•   No changes

    BEHAVIOR
•   Change user agent list                                                  BEHAVIOR
•   Add an email subscription form into the footer

•   Create an email subscription widget

    PRESENTATION                                             STRUCTURE
•   Widget and footer styling




                                                     Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                         USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                      PRESENTATION
•   No changes

    BEHAVIOR
•   Change user agent list                                                  BEHAVIOR
•   Add an email subscription form into the footer

•   Create an email subscription widget

    PRESENTATION                                             STRUCTURE
•   Widget and footer styling




                                                     Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                         USE         PATCH       BUILD
WHAT WE CHANGED

    STRUCTURE                                                                      PRESENTATION
•   No changes

    BEHAVIOR
•   Change user agent list                                                  BEHAVIOR
•   Add an email subscription form into the footer

•   Create an email subscription widget

    PRESENTATION                                             STRUCTURE
•   Widget and footer styling




                                                     Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large



                                                                         USE         PATCH       BUILD
Example Three
JIFFYPOSTS
EMBEDDED CONTENT
OUR STARTING POINT              http://bit.ly/ij3O9C




                     Embed.ly
OUR STARTING POINT
OUR STARTING POINT
WORKFLOW IMPROVEMENTS
WORKFLOW IMPROVEMENTS
<?php
add_action( 'init', 'argo_register_jiffypost_type' );
function argo_register_jiffypost_type() {
    register_post_type( 'jiffypost', array(
        'labels' => array(
            'name' => 'Jiffy Posts',
            'singular_name' => 'Jiffy Post',
        ),
        'description' => 'Jiffy Posts',
        'supports' => array( 'title', 'comments', 'author' ), # no editor!
        'public' => true,
        'menu_position' => 6,
        'taxonomies' => array(),
    ) );
}
                                                                                
add_filter( 'wp_insert_post_data', 'argo_insert_post_content' );
function argo_insert_post_content( $data ) {
    if ( 'jiffypost' != $data[ 'post_type' ] )
        return $data;
                                                                                
    $content = '';
    if ( isset( $_POST[ 'leadintext' ] ) ) {
        $content = '<p>' . $_POST[ 'leadintext' ] . '</p>';
    }
    if ( isset( $_POST[ 'embedlyarea' ] ) ) {
        $content .= $_POST[ 'embedlyarea' ];
    }
                                                                                
    $data[ 'post_content' ] = $content;
    return $data;
}
?>
WORKFLOW IMPROVEMENTS
<?php
add_meta_box( 'navisleadin', 'Lead in text', 'argo_embed_leadin_box',
    'jiffypost', 'normal', 'high' );
add_filter( 'teeny_mce_buttons', 'argo_modify_teeny_mce_buttons' ) );

function argo_embed_leadin_box( $post ) {
    $leadintext = get_post_meta( $post->ID, '_leadintext', true );

    wp_tiny_mce( true,
        array(
            'editor_selector' => 'leadintext',
            'setup' => 'tinyMCESetup',
        )
    );
?>
    <p align="right">
         <a id="edButtonHTML" class="">HTML</a>
         <a id="edButtonPreview" class="active">Visual</a>
    </p>
    <textarea id="leadintext" class="leadintext" name="leadintext" style="width: 98%"><?php
esc_textarea( $leadintext ); ?></textarea>
<?php
}

function argo_modify_teeny_mce_buttons( $buttons ) {
    if ( 'jiffypost' != get_post_type() )
        return $buttons;

    return array( 'bold', 'italic', 'underline', 'strikethrough',
        'link', 'unlink' );
}
?>
DESIGN IMPROVEMENTS
DESIGN IMPROVEMENTS
DESIGN IMPROVEMENTS




       LINK
                      PHOTO




       VIDEO           RICH
WHAT WE BUILT

    STRUCTURE                                                                                  PRESENTATION
•   Create a custom post type for embedded content

•   Keep requests for embedded content on the backend


    BEHAVIOR                                                                            BEHAVIOR
•   Create a customized TinyMCE editor for use with
    character-limited lead-in text

•   Preview/edit embedded content in post admin                          STRUCTURE
•   Provide proper attribution through source and via fields

•   Create bookmarklet for adding JiffyPosts off-site


    PRESENTATION
•   Provide formatting of all embed.ly content type responses.

•   Reveal hierarchy of original and embedded content

•   Introduce visual variety for different post types            Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large

•   Encourage interaction around embedded content on-site
                                                                                     USE         PATCH       BUILD
WHAT WE BUILT

    STRUCTURE                                                                                  PRESENTATION
•   Create a custom post type for embedded content

•   Keep requests for embedded content on the backend


    BEHAVIOR                                                                            BEHAVIOR
•   Create a customized TinyMCE editor for use with
    character-limited lead-in text

•   Preview/edit embedded content in post admin                          STRUCTURE
•   Provide proper attribution through source and via fields

•   Create bookmarklet for adding JiffyPosts off-site


    PRESENTATION
•   Provide formatting of all embed.ly content type responses.

•   Reveal hierarchy of original and embedded content

•   Introduce visual variety for different post types            Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large

•   Encourage interaction around embedded content on-site
                                                                                     USE         PATCH       BUILD
WHAT WE BUILT

    STRUCTURE                                                                                  PRESENTATION
•   Create a custom post type for embedded content

•   Keep requests for embedded content on the backend


    BEHAVIOR                                                                            BEHAVIOR
•   Create a customized TinyMCE editor for use with
    character-limited lead-in text

•   Preview/edit embedded content in post admin                          STRUCTURE
•   Provide proper attribution through source and via fields

•   Create bookmarklet for adding JiffyPosts off-site


    PRESENTATION
•   Provide formatting of all embed.ly content type responses.

•   Reveal hierarchy of original and embedded content

•   Introduce visual variety for different post types            Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large

•   Encourage interaction around embedded content on-site
                                                                                     USE         PATCH       BUILD
WHAT WE BUILT

    STRUCTURE                                                                                  PRESENTATION
•   Create a custom post type for embedded content

•   Keep requests for embedded content on the backend


    BEHAVIOR                                                                            BEHAVIOR
•   Create a customized TinyMCE editor for use with
    character-limited lead-in text

•   Preview/edit embedded content in post admin                          STRUCTURE
•   Provide proper attribution through source and via fields

•   Create bookmarklet for adding JiffyPosts off-site


    PRESENTATION
•   Provide formatting of all embed.ly content type responses.

•   Reveal hierarchy of original and embedded content

•   Introduce visual variety for different post types            Small      AMOUNT OF PLUGIN CUSTOMIZATION    Large

•   Encourage interaction around embedded content on-site
                                                                                     USE         PATCH       BUILD
LESSONS LEARNED




“I could tell you stories to curl your hair,
but it looks like you’ve already heard ‘em.”
                           — Barton Fink (1991)

                                         credit: iwdrm.tumblr.com
QUESTIONS?
             Marc Lavallee
             @lavallee

             Wesley Lindamood
             @lindamood

             Slideshare
             http://slidesha.re/qsJEmY




                             credit: iwdrm.tumblr.com

More Related Content

Similar to Plugins Are Blueprints

Talk Paris Infovis 091207132953 Phpapp01(2)
Talk Paris Infovis 091207132953 Phpapp01(2)Talk Paris Infovis 091207132953 Phpapp01(2)
Talk Paris Infovis 091207132953 Phpapp01(2)johnnybiz
 
Using Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the WebUsing Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the Webphilogb
 
Rapid Prototyping With jQuery
Rapid Prototyping With jQueryRapid Prototyping With jQuery
Rapid Prototyping With jQueryPaul Bakaus
 
CUST-2 New Client Configuration & Extension Points in Share
CUST-2 New Client Configuration & Extension Points in ShareCUST-2 New Client Configuration & Extension Points in Share
CUST-2 New Client Configuration & Extension Points in ShareAlfresco Software
 
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...Amazon Web Services
 
Single Page Applications - Desert Code Camp 2012
Single Page Applications - Desert Code Camp 2012Single Page Applications - Desert Code Camp 2012
Single Page Applications - Desert Code Camp 2012Adam Mokan
 
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon Baltimore
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon BaltimoreCreating Landing Pages and Layouts for Drupal 8 - DrupalCon Baltimore
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon BaltimoreSuzanne Dergacheva
 
Full Trust Solution Development in SharePoint 2013
Full Trust Solution Development in SharePoint 2013Full Trust Solution Development in SharePoint 2013
Full Trust Solution Development in SharePoint 2013Ed Musters
 
Best Practice Checklist for Building a Drupal Website
Best Practice Checklist for Building a Drupal WebsiteBest Practice Checklist for Building a Drupal Website
Best Practice Checklist for Building a Drupal WebsiteAcquia
 
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...Amazon Web Services
 
Putting the 'ctions' in Azure Fun-ctions
Putting the 'ctions' in Azure Fun-ctionsPutting the 'ctions' in Azure Fun-ctions
Putting the 'ctions' in Azure Fun-ctionsNullOps
 
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...Michael Rys
 
Advanced Silverlight
Advanced SilverlightAdvanced Silverlight
Advanced Silverlightrsnarayanan
 
Java script infovis toolkit
Java script infovis toolkitJava script infovis toolkit
Java script infovis toolkitnikhilyagnic
 
Station Four: Web Redesign Presentation
Station Four: Web Redesign PresentationStation Four: Web Redesign Presentation
Station Four: Web Redesign Presentationcolberding
 
Webpack and Web Performance Optimization
Webpack and Web Performance OptimizationWebpack and Web Performance Optimization
Webpack and Web Performance OptimizationChen-Tien Tsai
 

Similar to Plugins Are Blueprints (20)

Talk Paris Infovis 091207132953 Phpapp01(2)
Talk Paris Infovis 091207132953 Phpapp01(2)Talk Paris Infovis 091207132953 Phpapp01(2)
Talk Paris Infovis 091207132953 Phpapp01(2)
 
Using Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the WebUsing Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the Web
 
Rapid Prototyping With jQuery
Rapid Prototyping With jQueryRapid Prototyping With jQuery
Rapid Prototyping With jQuery
 
CUST-2 New Client Configuration & Extension Points in Share
CUST-2 New Client Configuration & Extension Points in ShareCUST-2 New Client Configuration & Extension Points in Share
CUST-2 New Client Configuration & Extension Points in Share
 
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...
AWS Summit Sydney 2014 | Continuous Integration and Deployment Best Practices...
 
Single Page Applications - Desert Code Camp 2012
Single Page Applications - Desert Code Camp 2012Single Page Applications - Desert Code Camp 2012
Single Page Applications - Desert Code Camp 2012
 
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon Baltimore
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon BaltimoreCreating Landing Pages and Layouts for Drupal 8 - DrupalCon Baltimore
Creating Landing Pages and Layouts for Drupal 8 - DrupalCon Baltimore
 
Full Trust Solution Development in SharePoint 2013
Full Trust Solution Development in SharePoint 2013Full Trust Solution Development in SharePoint 2013
Full Trust Solution Development in SharePoint 2013
 
Best Practice Checklist for Building a Drupal Website
Best Practice Checklist for Building a Drupal WebsiteBest Practice Checklist for Building a Drupal Website
Best Practice Checklist for Building a Drupal Website
 
Enterprise Dev and Test on AWS
Enterprise Dev and Test on AWSEnterprise Dev and Test on AWS
Enterprise Dev and Test on AWS
 
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...
AWS Summit Auckland 2014 | Continuous Integration and Deployment Best Practic...
 
Putting the 'ctions' in Azure Fun-ctions
Putting the 'ctions' in Azure Fun-ctionsPutting the 'ctions' in Azure Fun-ctions
Putting the 'ctions' in Azure Fun-ctions
 
Bower power
Bower powerBower power
Bower power
 
FusionCharts Clockworks
FusionCharts ClockworksFusionCharts Clockworks
FusionCharts Clockworks
 
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...
Bring your code to explore the Azure Data Lake: Execute your .NET/Python/R co...
 
Advanced Silverlight
Advanced SilverlightAdvanced Silverlight
Advanced Silverlight
 
Java script infovis toolkit
Java script infovis toolkitJava script infovis toolkit
Java script infovis toolkit
 
Station Four: Web Redesign Presentation
Station Four: Web Redesign PresentationStation Four: Web Redesign Presentation
Station Four: Web Redesign Presentation
 
Webpack and Web Performance Optimization
Webpack and Web Performance OptimizationWebpack and Web Performance Optimization
Webpack and Web Performance Optimization
 
Css framework
Css frameworkCss framework
Css framework
 

Recently uploaded

How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 

Recently uploaded (20)

How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 

Plugins Are Blueprints

  • 1. PLUGINS ARE BLUEPRINTS Decoding the presentation, behavior and structure of WordPress plugins to make them your own WordCamp Boston 2011 Marc Lavallee, @lavallee Wesley Lindamood, @lindamood Credit: Chris Ware- Building Stories
  • 2. PLUGINS ARE BLUEPRINTS Decoding the presentation, behavior and structure of WordPress plugins to make them your own WordCamp Boston 2011 Marc Lavallee, @lavallee Wesley Lindamood, @lindamood Credit: Chris Ware- Building Stories
  • 4. COHERENCE Credit: David Arpi/Flickr
  • 5. DECODING A PLUGIN http://bit.ly/pKLC7I Credit: Bob Baxley
  • 6. PLUGIN USAGE USE PATCH BUILD • W3 Total Cache • Google Analyticator • FD Feedburner • Slides for WordPress • Embed.ly • Link Roundup Use Patch Prototype and Draw inspiration Start from as-is customize scratch
  • 7. PLUGIN USAGE USE PATCH BUILD • W3 Total Cache • Google Analyticator • FD Feedburner • Slides for WordPress • Embed.ly • Link Roundup Use Patch Prototype and Draw inspiration Start from as-is customize scratch
  • 8. CUSTOMIZING PLUGINS 1 Find the best available plugin 2 Explore through prototyping 3 Decide to build or patch 4 Begin development
  • 9. AN EDUCATED GUESS PRESENTATION BEHAVIOR STRUCTURE
  • 10. WHEN TO USE A PLUGIN PRESENTATION USE BEHAVIOR STRUCTURE Small AMOUNT OF PLUGIN CUSTOMIZATION Large
  • 11. WHEN TO PATCH A PLUGIN PRESENTATION USE BEHAVIOR PATCH STRUCTURE Small AMOUNT OF PLUGIN CUSTOMIZATION Large
  • 12. WHEN TO BUILD YOUR OWN PLUGIN PRESENTATION USE BEHAVIOR PATCH STRUCTURE BUILD Small AMOUNT OF PLUGIN CUSTOMIZATION Large
  • 14. A LIVING PATTERN LIBRARY Credit: Mark Killingsworth I start where the last man left off — Thomas Edison
  • 15. OUR STARTING POINT http://bit.ly/gKHLvt Slides for WordPress
  • 19. CONDITIONAL IMAGE LOADING http://bit.ly/pab-images ELEMENT BEFORE <div id="7118-slide3" data-src="http://e.opb.org/files/2011/07/3.jpg*450*600" /> ELEMENT AFTER <div id="7118-slide2"><img src="http://e.opb.org/files/2011/07/3.jpg" width="620" height="465" /> JAVASCRIPT function ensureImageIsLoaded( postID, slideNum ) {     var slideDiv = jQuery( "#" + getSlideElement( postID, slideNum ) );     // Do nothing if the slide image already exists     if ( slideDiv.has( "img" ).length )         return;     var imgData = slideDiv.attr( "data-src" );     if ( imgData ) {         var parts = imgData.split( "*" );         var img = jQuery( "<img/>" )             .attr( "src", parts[0] )             .attr( "width", parts[1] )             .attr( "height", parts[2] );         slideDiv.prepend( img );     } }
  • 20. CONDITIONAL SCRIPT LOADING http://bit.ly/pab-scripts <?php $argo_include_slideshow_deps = false; add_filter( 'post_gallery', 'argo_handle_slideshow', 10, 2 ); add_filter( 'wp_footer', 'argo_add_slideshow_deps' ); function argo_handle_slideshow( $output, $attr ) {     global $argo_include_slideshow_deps;     $argo_include_slideshow_deps = true;     return do_other_slideshow_things( $output, $attr ); } function argo_add_slideshow_deps() {     global $argo_include_slideshow_deps;     if ( ! $argo_include_slideshow_deps ) { return; }     // jQuery slides plugin from http://slidesjs.com/     $slides_src = plugins_url( 'js/slides.min.jquery.js', __FILE__ );     wp_register_script( 'jquery-slides', $slides_src, array ( 'jquery' ), '1.1.7', true );     wp_print_scripts( 'jquery-slides' ); } ?>
  • 21. PLUGIN SEDIMENT SLIDES FOR WORDPRESS PHP: 39k 895 lines 748 sloc NAVIS SLIDESHOWS PHP: 8k 244 lines 199 sloc
  • 22. WHAT WE CHANGED STRUCTURE PRESENTATION • Remove unneeded options and features BEHAVIOR • Conditionally load slideshow CSS, JS BEHAVIOR • Dynamically load images • Add custom taxonomy for sideshow content type • Add image permalinks STRUCTURE PRESENTATION • Add credit and caption • Adjust placement of UI controls, the width of images and look and feel of the slideshow to conform to Argo standards. Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 23. WHAT WE CHANGED STRUCTURE PRESENTATION • Remove unneeded options and features BEHAVIOR • Conditionally load slideshow CSS, JS BEHAVIOR • Dynamically load images • Add custom taxonomy for sideshow content type • Add image permalinks STRUCTURE PRESENTATION • Add credit and caption • Adjust placement of UI controls, the width of images and look and feel of the slideshow to conform to Argo standards. Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 24. WHAT WE CHANGED STRUCTURE PRESENTATION • Remove unneeded options and features BEHAVIOR • Conditionally load slideshow CSS, JS BEHAVIOR • Dynamically load images • Add custom taxonomy for sideshow content type • Add image permalinks STRUCTURE PRESENTATION • Add credit and caption • Adjust placement of UI controls, the width of images and look and feel of the slideshow to conform to Argo standards. Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 25. WHAT WE CHANGED STRUCTURE PRESENTATION • Remove unneeded options and features BEHAVIOR • Conditionally load slideshow CSS, JS BEHAVIOR • Dynamically load images • Add custom taxonomy for sideshow content type • Add image permalinks STRUCTURE PRESENTATION • Add credit and caption • Adjust placement of UI controls, the width of images and look and feel of the slideshow to conform to Argo standards. Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 27. OUR STARTING POINT http://bit.ly/gbx4j2 FD Feedburner
  • 29. MENU PLACEMENT <?php // In our theme's functions.php file if ( function_exists( 'feedburner_config_page' ) ) {     add_submenu_page( 'plugins.php','Feedburner Configuration', 'Feedburner Configuration',         'manage_options', 'argo_feedburner_menu', 'feedburner_conf' );     remove_submenu_page( 'plugins.php', 'fdfeedburner.php' ); } ?>
  • 30. USER AGENT CUSTOMIZATIONS <?php // In FD Feedburner plugin function feedburner_redirect() {     global $feed, $withcomments, $wp, $wpdb, $wp_version, $wp_db_version;     do_a_bunch_of_stuff();     // Do nothing if not a feed     if (!is_feed()) return;     $skip_useragents = array( '/feedburner/i', '/googlebot/i' );     $skip_useragents = apply_filters( 'feedburner_skip_useragents', $skip_useragents );     foreach ( $skip_useragents as $ua ) {         if ( preg_match( $ua, $_SERVER[ 'HTTP_USER_AGENT' ] ) ) return;     }     do_more_stuff(); } ?> <?php // In our theme add_filter( 'feedburner_skip_useragents', 'argo_allow_yahoo_pipes' ); function argo_allow_yahoo_pipes( $useragents ) {     $useragents[] = '/yahoo pipes/i';     return $useragents; } ?>
  • 31. WHAT WE CHANGED STRUCTURE PRESENTATION • No changes BEHAVIOR • Change user agent list BEHAVIOR • Add an email subscription form into the footer • Create an email subscription widget PRESENTATION STRUCTURE • Widget and footer styling Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 32. WHAT WE CHANGED STRUCTURE PRESENTATION • No changes BEHAVIOR • Change user agent list BEHAVIOR • Add an email subscription form into the footer • Create an email subscription widget PRESENTATION STRUCTURE • Widget and footer styling Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 33. WHAT WE CHANGED STRUCTURE PRESENTATION • No changes BEHAVIOR • Change user agent list BEHAVIOR • Add an email subscription form into the footer • Create an email subscription widget PRESENTATION STRUCTURE • Widget and footer styling Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 34. WHAT WE CHANGED STRUCTURE PRESENTATION • No changes BEHAVIOR • Change user agent list BEHAVIOR • Add an email subscription form into the footer • Create an email subscription widget PRESENTATION STRUCTURE • Widget and footer styling Small AMOUNT OF PLUGIN CUSTOMIZATION Large USE PATCH BUILD
  • 37. OUR STARTING POINT http://bit.ly/ij3O9C Embed.ly
  • 41. WORKFLOW IMPROVEMENTS <?php add_action( 'init', 'argo_register_jiffypost_type' ); function argo_register_jiffypost_type() {     register_post_type( 'jiffypost', array(         'labels' => array(             'name' => 'Jiffy Posts',             'singular_name' => 'Jiffy Post',         ),         'description' => 'Jiffy Posts',         'supports' => array( 'title', 'comments', 'author' ), # no editor!         'public' => true,         'menu_position' => 6,         'taxonomies' => array(),     ) ); }                                                                                  add_filter( 'wp_insert_post_data', 'argo_insert_post_content' ); function argo_insert_post_content( $data ) {     if ( 'jiffypost' != $data[ 'post_type' ] )         return $data;                                                                                      $content = '';     if ( isset( $_POST[ 'leadintext' ] ) ) {         $content = '<p>' . $_POST[ 'leadintext' ] . '</p>';     }     if ( isset( $_POST[ 'embedlyarea' ] ) ) {         $content .= $_POST[ 'embedlyarea' ];     }                                                                                      $data[ 'post_content' ] = $content;     return $data; } ?>
  • 42. WORKFLOW IMPROVEMENTS <?php add_meta_box( 'navisleadin', 'Lead in text', 'argo_embed_leadin_box',     'jiffypost', 'normal', 'high' ); add_filter( 'teeny_mce_buttons', 'argo_modify_teeny_mce_buttons' ) ); function argo_embed_leadin_box( $post ) {     $leadintext = get_post_meta( $post->ID, '_leadintext', true );     wp_tiny_mce( true,         array(             'editor_selector' => 'leadintext',             'setup' => 'tinyMCESetup',         )     ); ?> <p align="right"> <a id="edButtonHTML" class="">HTML</a> <a id="edButtonPreview" class="active">Visual</a> </p> <textarea id="leadintext" class="leadintext" name="leadintext" style="width: 98%"><?php esc_textarea( $leadintext ); ?></textarea> <?php } function argo_modify_teeny_mce_buttons( $buttons ) {     if ( 'jiffypost' != get_post_type() )         return $buttons;     return array( 'bold', 'italic', 'underline', 'strikethrough',         'link', 'unlink' ); } ?>
  • 45. DESIGN IMPROVEMENTS LINK PHOTO VIDEO RICH
  • 46. WHAT WE BUILT STRUCTURE PRESENTATION • Create a custom post type for embedded content • Keep requests for embedded content on the backend BEHAVIOR BEHAVIOR • Create a customized TinyMCE editor for use with character-limited lead-in text • Preview/edit embedded content in post admin STRUCTURE • Provide proper attribution through source and via fields • Create bookmarklet for adding JiffyPosts off-site PRESENTATION • Provide formatting of all embed.ly content type responses. • Reveal hierarchy of original and embedded content • Introduce visual variety for different post types Small AMOUNT OF PLUGIN CUSTOMIZATION Large • Encourage interaction around embedded content on-site USE PATCH BUILD
  • 47. WHAT WE BUILT STRUCTURE PRESENTATION • Create a custom post type for embedded content • Keep requests for embedded content on the backend BEHAVIOR BEHAVIOR • Create a customized TinyMCE editor for use with character-limited lead-in text • Preview/edit embedded content in post admin STRUCTURE • Provide proper attribution through source and via fields • Create bookmarklet for adding JiffyPosts off-site PRESENTATION • Provide formatting of all embed.ly content type responses. • Reveal hierarchy of original and embedded content • Introduce visual variety for different post types Small AMOUNT OF PLUGIN CUSTOMIZATION Large • Encourage interaction around embedded content on-site USE PATCH BUILD
  • 48. WHAT WE BUILT STRUCTURE PRESENTATION • Create a custom post type for embedded content • Keep requests for embedded content on the backend BEHAVIOR BEHAVIOR • Create a customized TinyMCE editor for use with character-limited lead-in text • Preview/edit embedded content in post admin STRUCTURE • Provide proper attribution through source and via fields • Create bookmarklet for adding JiffyPosts off-site PRESENTATION • Provide formatting of all embed.ly content type responses. • Reveal hierarchy of original and embedded content • Introduce visual variety for different post types Small AMOUNT OF PLUGIN CUSTOMIZATION Large • Encourage interaction around embedded content on-site USE PATCH BUILD
  • 49. WHAT WE BUILT STRUCTURE PRESENTATION • Create a custom post type for embedded content • Keep requests for embedded content on the backend BEHAVIOR BEHAVIOR • Create a customized TinyMCE editor for use with character-limited lead-in text • Preview/edit embedded content in post admin STRUCTURE • Provide proper attribution through source and via fields • Create bookmarklet for adding JiffyPosts off-site PRESENTATION • Provide formatting of all embed.ly content type responses. • Reveal hierarchy of original and embedded content • Introduce visual variety for different post types Small AMOUNT OF PLUGIN CUSTOMIZATION Large • Encourage interaction around embedded content on-site USE PATCH BUILD
  • 50. LESSONS LEARNED “I could tell you stories to curl your hair, but it looks like you’ve already heard ‘em.” — Barton Fink (1991) credit: iwdrm.tumblr.com
  • 51. QUESTIONS? Marc Lavallee @lavallee Wesley Lindamood @lindamood Slideshare http://slidesha.re/qsJEmY credit: iwdrm.tumblr.com