CINXE.COM

October | 2008 | code.flickr.com

<!DOCTYPE html> <!--[if IE 6]> <html id="ie6" lang="en-US"> <![endif]--> <!--[if IE 7]> <html id="ie7" lang="en-US"> <![endif]--> <!--[if IE 8]> <html id="ie8" lang="en-US"> <![endif]--> <!--[if !(IE 6) & !(IE 7) & !(IE 8)]><!--> <html lang="en-US"> <!--<![endif]--> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <title> October | 2008 | code.flickr.com </title> <link rel="profile" href="https://gmpg.org/xfn/11" /> <link rel="stylesheet" type="text/css" media="all" href="https://code.flickr.net/wp-content/themes/flickr-code/style.css?ver=20190507" /> <link rel="pingback" href="https://code.flickr.net/xmlrpc.php"> <!--[if lt IE 9]> <script src="https://code.flickr.net/wp-content/themes/twentyeleven/js/html5.js?ver=3.7.0" type="text/javascript"></script> <![endif]--> <meta name='robots' content='max-image-preview:large' /> <style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style> <link rel='dns-prefetch' href='//stats.wp.com' /> <link rel="alternate" type="application/rss+xml" title="code.flickr.com &raquo; Feed" href="https://code.flickr.net/feed/" /> <link rel="alternate" type="application/rss+xml" title="code.flickr.com &raquo; Comments Feed" href="https://code.flickr.net/comments/feed/" /> <script type="text/javascript"> /* <![CDATA[ */ window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/code.flickr.net\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.7.2"}}; /*! This file is auto-generated */ !function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\u2b1b","\ud83d\udc26\u200b\u2b1b")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings); /* ]]> */ </script> <style id='wp-emoji-styles-inline-css'> img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } </style> <link rel='stylesheet' id='all-css-2' href='https://code.flickr.net/wp-includes/css/dist/block-library/style.min.css?m=1739294329g' type='text/css' media='all' /> <style id='wp-block-library-theme-inline-css'> .wp-block-audio :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-audio :where(figcaption){color:#ffffffa6}.wp-block-audio{margin:0 0 1em}.wp-block-code{border:1px solid #ccc;border-radius:4px;font-family:Menlo,Consolas,monaco,monospace;padding:.8em 1em}.wp-block-embed :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-embed :where(figcaption){color:#ffffffa6}.wp-block-embed{margin:0 0 1em}.blocks-gallery-caption{color:#555;font-size:13px;text-align:center}.is-dark-theme .blocks-gallery-caption{color:#ffffffa6}:root :where(.wp-block-image figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme :root :where(.wp-block-image figcaption){color:#ffffffa6}.wp-block-image{margin:0 0 1em}.wp-block-pullquote{border-bottom:4px solid;border-top:4px solid;color:currentColor;margin-bottom:1.75em}.wp-block-pullquote cite,.wp-block-pullquote footer,.wp-block-pullquote__citation{color:currentColor;font-size:.8125em;font-style:normal;text-transform:uppercase}.wp-block-quote{border-left:.25em solid;margin:0 0 1.75em;padding-left:1em}.wp-block-quote cite,.wp-block-quote footer{color:currentColor;font-size:.8125em;font-style:normal;position:relative}.wp-block-quote:where(.has-text-align-right){border-left:none;border-right:.25em solid;padding-left:0;padding-right:1em}.wp-block-quote:where(.has-text-align-center){border:none;padding-left:0}.wp-block-quote.is-large,.wp-block-quote.is-style-large,.wp-block-quote:where(.is-style-plain){border:none}.wp-block-search .wp-block-search__label{font-weight:700}.wp-block-search__button{border:1px solid #ccc;padding:.375em .625em}:where(.wp-block-group.has-background){padding:1.25em 2.375em}.wp-block-separator.has-css-opacity{opacity:.4}.wp-block-separator{border:none;border-bottom:2px solid;margin-left:auto;margin-right:auto}.wp-block-separator.has-alpha-channel-opacity{opacity:1}.wp-block-separator:not(.is-style-wide):not(.is-style-dots){width:100px}.wp-block-separator.has-background:not(.is-style-dots){border-bottom:none;height:1px}.wp-block-separator.has-background:not(.is-style-wide):not(.is-style-dots){height:2px}.wp-block-table{margin:0 0 1em}.wp-block-table td,.wp-block-table th{word-break:normal}.wp-block-table :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-table :where(figcaption){color:#ffffffa6}.wp-block-video :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-video :where(figcaption){color:#ffffffa6}.wp-block-video{margin:0 0 1em}:root :where(.wp-block-template-part.has-background){margin-bottom:0;margin-top:0;padding:1.25em 2.375em} </style> <link rel='stylesheet' id='all-css-6' href='https://code.flickr.net/_static/??-eJzTLy/QzcxLzilNSS3WzyrWz01NyUxMzUnNTc0rQeEU5CRWphbp5qSmJyZX6uVm5uklFxfr6OPTDpRD5sM02efaGpobWxpZmhgbGwAAROEu5A==' type='text/css' media='all' /> <style id='jetpack-sharing-buttons-style-inline-css'> .jetpack-sharing-buttons__services-list{display:flex;flex-direction:row;flex-wrap:wrap;gap:0;list-style-type:none;margin:5px;padding:0}.jetpack-sharing-buttons__services-list.has-small-icon-size{font-size:12px}.jetpack-sharing-buttons__services-list.has-normal-icon-size{font-size:16px}.jetpack-sharing-buttons__services-list.has-large-icon-size{font-size:24px}.jetpack-sharing-buttons__services-list.has-huge-icon-size{font-size:36px}@media print{.jetpack-sharing-buttons__services-list{display:none!important}}.editor-styles-wrapper .wp-block-jetpack-sharing-buttons{gap:0;padding-inline-start:0}ul.jetpack-sharing-buttons__services-list.has-background{padding:1.25em 2.375em} </style> <style id='classic-theme-styles-inline-css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <style id='global-styles-inline-css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--blue: #1982d1;--wp--preset--color--dark-gray: #373737;--wp--preset--color--medium-gray: #666;--wp--preset--color--light-gray: #e2e2e2;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} </style> <link rel='stylesheet' id='all-css-12' href='https://code.flickr.net/_static/??-eJzTLy/QTc7PK0nNK9EvyUjNTS3WLykHcipTc1LLUvP0i0sqc1L1kouLdfQxVablZCZnFwFFU1LxK0QxMiknPzm7GKTUPtfW0NzYxNDA3NzQAABaZTMQ' type='text/css' media='all' /> <link rel="https://api.w.org/" href="https://code.flickr.net/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://code.flickr.net/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress 6.7.2" /> <style>img#wpstats{display:none}</style> <style type="text/css" id="twentyeleven-header-css"> #site-title, #site-description { position: absolute; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } </style> <style type="text/css" id="wp-custom-css"> body { background: #fff; } body,input,textarea { font-family: Arial, sans-serif; color: #404040; } #page { margin: 1em auto; max-width: 1000px; } a:link { text-decoration: none; color: #0063dc; } a:visited { text-decoration: none; color: #0063dc; } a:hover { text-decoration: none; background: #0063dc; color: #fff; } a:active { text-decoration: none; background-color: #0259c4; color: #fff; } #branding { border: none; } #branding .only-search #s,#branding .only-search #s:focus { width: 280px; background-color: transparent; border-color: #ddd; } #branding #searchform { right: 0; } nav#access { background: none; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none; margin: 0; } nav#access a { font-weight: bold; margin: 11px 28px 0 0; padding: 0; line-height: 21px; } nav#access a:link,nav#access a:visited { text-decoration: none; color: #888; } nav#access a:hover,nav#access li:hover > a,nav#access a:focus,nav#access a:active { text-decoration: none; color: #0063dc; background: none; } #branding .only-search + nav#access div { padding-right: 300px; } nav#access div,nav#access ul { margin: 0; } @media screen and (max-width: 768px) { #branding .only-search + nav#access div { padding-right: 0; } #branding #searchform { display: none; position: static; text-align: center; } #branding .with-image #searchform { max-width: 100%; } #branding .only-search #s,#branding .only-search #s:focus { width: 85%; float: none; } nav#access { margin: 0 0 0 5%; } } @media screen and (max-width: 480px) { nav#access { display: none; } } #content { margin: 0 20% 0 0; width: 80%; } #content .comments-link { display: none; } @media screen and (max-width: 800px) { #main { padding-top: 0; overflow: hidden; } #branding { padding-bottom: 0; } #main #content { margin: 0; } .entry-title,.entry-header .entry-meta { padding-right: 0; } } .singular #content,.left-sidebar.singular #content { margin: 0 10%; width: 80%; } .singular .entry-header,.singular .entry-content,.singular footer.entry-meta,.singular #comments-title { width: 100%; } .hentry,.no-results { border-bottom: 1px dotted #dadada; } .singular .hentry { padding-top: 1em; } .entry-title { padding-bottom: 0; } .entry-title,.entry-title a { font-size: 28px; color: #000; } .entry-title a:hover,.entry-title a:focus,.entry-title a:active { color: #0063dc; background-color: transparent; } @media screen and (max-width: 650px) { .singular .entry-title { padding-top: 0; line-height: 42px; } } .singular .entry-content { margin-top: 0; } #jp-post-flair { margin-top: 3em; } footer.entry-meta .cat-links,footer.entry-meta .sep,footer.entry-meta .tag-links { display: none; } .singular .entry-meta .edit-link a { position: static; } .singular footer.entry-meta { margin-top: 2em; } #comments { display: none; } #site-generator { background: transparent; border-top: none; padding: 0 .5em; } img#wpstats { position: absolute !important; clip: rect(1px 1px 1px 1px); } #secondary { margin-right: 0; width: 16%; text-align: right; } #secondary #s { display: none; } #secondary aside ul { list-style: none; } #secondary .widget-title { color: #999; font-size: 12px; letter-spacing: auto; text-transform: none; } .widget a { font-weight: normal; } .widget a:hover,.widget a:focus,.widget a:active { text-decoration: none; } #everything-after-this-line-is-a-post-level-style---yay-for-wordpress-stripping-comments-from-css { color: #000; } .entry-content p { margin-bottom: 1.3em; } .entry-content p.note { padding: 11px; background-color: #fffdeb; border-bottom: 1px solid #fff9c2; } .entry-content p.warning { padding: 11px; background-color: #fdf8f8; border-bottom: 1px solid #f7dedd; } .entry-content .aside { margin-bottom: 1.3em; padding: 11px; background-color: #f8fdf8; border-bottom: 1px solid #def6df; } .entry-content .aside p:last-child { margin-bottom: 0; } .entry-content h2,.entry-content h3,.entry-content h4 { font-weight: bold; color: #000; text-transform: none; } .entry-content h2 { font-size: 22px; } .entry-content h3 { font-size: 16px; letter-spacing: 0; line-height: 1.3em; margin-bottom: 1em; } .entry-content h4 { font-size: 13px; line-height: 1.4em; margin-bottom: 0; } .entry-content p.flickr-photo,.entry-content p.flickr-photo a,.entry-content p.figure { color: #999; font-size: 14px; } .entry-content p.flickr-photo a:hover,.entry-content p.flickr-photo a:active { color: #0063dc; background-color: transparent; } .entry-content p.flickr-photo .caption { display: block; padding-left: 22px; background: url('http://farm4.staticflickr.com/3329/favicons/72157601614001242_7730.png') no-repeat 0 3px; } .entry-content img { max-width: 100%; height: auto; } .undersized-image-container { text-align: center; } .entry-content code { color: #000; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; font-size: 14px; background-color: #F6FcFF; border-bottom: 1px solid #ebf5ff; } .entry-content ul { list-style: disc; } .entry-content ol ol { list-style: lower-alpha; } .entry-content table caption { font-size: 13px; font-weight: bold; color: #000; } .entry-content table tr.odd td,.entry-content table tr.odd th { background-color: #f8f8f8; } .entry-content table td,.entry-content table th { padding: 3px 10px; line-height: 1.4em; } .entry-content table tr th { color: #000; font-weight: bold; text-transform: none; font-size: 13px; letter-spacing: 0; border-top: 1px solid #ddd; } .entry-content table tr td { font-size: 14px; } .entry-content table.data tr td,.entry-content table.data thead tr th { text-align: right; } .entry-content table.tight td,.entry-content table.tight th { padding: 3px 6px; } .entry-content table.tight th { font-size: 12px; } .entry-content table.tight td { font-size: 13px; } @media screen and (max-width: 650px) { .entry-content table td,.entry-content table th { padding: 3px 5px; } .entry-content table tr th { font-size: 12px; } .entry-content table tr td { font-size: 13px; } .entry-content table.tight td,.entry-content table.tight th { padding: 3px 4px; } .entry-content table.tight th { font-size: 11px; } .entry-content table.tight td { font-size: 12px; } } .entry-content blockquote { font-family: inherit; font-style: normal; font-weight: normal; margin: 0 2em 1.3em; padding: 1em; background: #F9F9F9; border-bottom: 1px solid #ececec; } .entry-content blockquote p.source { margin-bottom: 0; } .entry-content .hiring-banner { position: relative; background: #ffebf5; padding: 11px 11px 11px 88px; border-bottom: 1px solid #ffc5e2; margin: 2em 0; } .entry-content .hiring-banner p { margin-bottom: 0; } .entry-content .hiring-banner .group-photo { position: absolute; left: -57px; top: -5px; width: 120px; padding: 6px; background: #fff; -webkit-box-shadow: 1px 1px 8px rgba(50,50,50,0.8); -moz-box-shadow: 1px 1px 8px rgba(50,50,50,0.8); box-shadow: 1px 1px 8px rgba(50,50,50,0.8); -webkit-transform: rotate(-11deg); -moz-transform: rotate(-11deg); -o-transform: rotate(-11deg); -ms-transform: rotate(-11deg); } .entry-content .hiring-banner .group-photo img { display: block; margin: 0; max-width: 100%; } @media screen and (max-width: 800px) { .entry-content .hiring-banner { padding-left: 11px; } .entry-content .hiring-banner .group-photo { display: none; } } #everything-after-this-line-is-for-the-syntaxhighlighter---all-rules-require-important { color: #000; } #main .syntaxhighlighter .lines { border-bottom: 1px solid #ebf5ff !important; } #main .syntaxhighlighter,#main .syntaxhighlighter div,#main .syntaxhighlighter code,#main .syntaxhighlighter table,#main .syntaxhighlighter table td,#main .syntaxhighlighter table tr,#main .syntaxhighlighter table tbody { font-size: 14px !important; } #main .syntaxhighlighter .line.alt1,#main .syntaxhighlighter .line.alt2 { background-color: #fafdff !important; } #main .syntaxhighlighter .line.highlighted { background-color: #fffbd6 !important; } #main .syntaxhighlighter .plain,#main .syntaxhighlighter .plain a { color: #000 !important; } #main .syntaxhighlighter .comments,#main .syntaxhighlighter .comments a { color: #999 !important; } #main .syntaxhighlighter .string,#main .syntaxhighlighter .string a { color: #ff52a9 !important; } #main .syntaxhighlighter .keyword { color: #0034fe !important; font-weight: normal !important; } #main .syntaxhighlighter .preprocessor { color: #417ba9 !important; } #main .syntaxhighlighter .variable { color: #b130c0 !important; } #main .syntaxhighlighter .value { color: #6b77f7 !important; } #main .syntaxhighlighter .functions { color: #002ad5 !important; } #main .syntaxhighlighter .constants { color: #d11e08 !important; } #main .syntaxhighlighter .script { background-color: yellow !important; } #main .syntaxhighlighter .color1,#main .syntaxhighlighter .color1 a { color: #808080 !important; } #main .syntaxhighlighter .color2,#main .syntaxhighlighter .color2 a { color: #ff1493 !important; } #main .syntaxhighlighter .color3,#main .syntaxhighlighter .color3 a { color: red !important; } a[data-flickr-embed] img { width: 800px; } </style> </head> <body class="archive date custom-background wp-embed-responsive jps-theme-flickr-code two-column right-sidebar"> <div class="skip-link"><a class="assistive-text" href="#content">Skip to primary content</a></div><div class="skip-link"><a class="assistive-text" href="#secondary">Skip to secondary content</a></div><div id="page" class="hfeed"> <header id="branding"> <hgroup> <h1 id="site-title"><span><a href="https://code.flickr.net/" rel="home">code.flickr.com</a></span></h1> <h2 id="site-description"></h2> </hgroup> <a href="https://code.flickr.net/"> <img src="https://wp.flickr.net/wp-content/uploads/sites/3/2012/09/code-flickr-com-drawn-header-grey-large.png" width="1000" height="157" alt="code.flickr.com" /> </a> <div class="only-search with-image"> <form method="get" id="searchform" action="https://code.flickr.net/"> <label for="s" class="assistive-text">Search</label> <input type="text" class="field" name="s" id="s" placeholder="Search" /> <input type="submit" class="submit" name="submit" id="searchsubmit" value="Search" /> </form> </div> <nav id="access"> <h3 class="assistive-text">Main menu</h3> <div class="menu-menu-container"><ul id="menu-menu" class="menu"><li id="menu-item-2084" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2084"><a href="http://www.flickr.com/">Flickr</a></li> <li id="menu-item-2085" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2085"><a href="http://blog.flickr.net/">Flickr Blog</a></li> <li id="menu-item-2250" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2250"><a href="http://twitter.com/flickr">@flickr</a></li> <li id="menu-item-2086" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2086"><a href="http://twitter.com/flickrapi">@flickrapi</a></li> <li id="menu-item-2087" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2087"><a href="https://www.flickr.com/services/developer/">Developer Guidelines</a></li> <li id="menu-item-2088" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2088"><a href="http://www.flickr.com/services/api/">API</a></li> <li id="menu-item-2089" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2089"><a href="http://www.flickr.com/jobs/">Jobs</a></li> </ul></div> </nav><!-- #access --> </header><!-- #branding --> <div id="main"> <section id="primary"> <div id="content" role="main"> <header class="page-header"> <h1 class="page-title"> Monthly Archives: <span>October 2008</span> </h1> </header> <article id="post-278" class="post-278 post type-post status-publish format-standard hentry category-geo tag-clustr tag-geo"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/30/the-shape-of-alpha/" rel="bookmark">The Shape of Alpha</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/30/the-shape-of-alpha/" title="9:21 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-30T21:21:51-07:00">October 30, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <div style="margin-top:20px;margin-bottom:20px;"> <a href="http://www.flickr.com/photos/straup/2853741772/" title="Untitled #1221325485 by straup, on Flickr"><img fetchpriority="high" decoding="async" src="http://farm4.static.flickr.com/3092/2853741772_928938d420.jpg" width="500" height="375" alt="Untitled #1221325485" style="border:1px dotted #ccc;padding:10px;" /></a> </div> <h2 style="margin-bottom:15px;">We have a lot of geotagged photos</h2> <p>Almost ninety million, as I write this, and the numbers keep growing especially as nearly every new <q>smart</q> phone released to market has not only a camera but also the ability to capture location information with it.</p> <p>For every geotagged photo we store up to six <a href="http://developer.yahoo.com/geo/">Where On Earth (WOE)</a> IDs. These are unique numeric identifiers that correspond to the hierarchy of places where a photo was taken: the neighbourhood, the town, the county, and so on up to the continent. This process is usually referred to as <a href="http://code.flickr.com/blog/2008/09/04/whos-on-first/">reverse-geocoding</a>.</p> <p>Over time this got us wondering: If we plotted all the geotagged photos associated with a particular WOE ID, would we have enough data to generate a mostly accurate contour of that place? Not a perfect representation, perhaps, but something more fine-grained than a bounding box. It turns out we can.</p> <p>So, starting today there are 150,000 (and counting) WOE IDs with proper (-ish) shape data, available via the <a href="http://www.flickr.com/services/api">Flickr API</a>. What kind of shapes, you ask?</p> <p>Continents:</p> <table> <tr> <td><a href="http://flickr.com/photos/straup/2986605405/"><img decoding="async" src="http://farm4.static.flickr.com/3161/2986605405_f50d14c3dc_m.jpg" style="border:none;" /></a></td> <td width="5%;">&nbsp;</td> <td valign="top"><a href="http://flickr.com/photos/straup/2986605381/"><img decoding="async" src="http://farm4.static.flickr.com/3153/2986605381_11c2007119_m.jpg"style="border:none;" /></a></td> </tr> </table> <p>Countries:</p> <table> <tr> <td><a href="http://flickr.com/photos/straup/2972130238/"><img decoding="async" src="http://farm4.static.flickr.com/3004/2972130238_70c47e52b3_m.jpg" style="border:none;" /></a></td> <td width="5%;">&nbsp;</td> <td><a href="http://flickr.com/photos/straup/2972130754/"><img decoding="async" src="http://farm4.static.flickr.com/3210/2972130754_71fe99ae37_m.jpg"style="border:none;" /></a></td> </tr> </table> <p>States and cities:</p> <table> <tr> <td><a href="http://flickr.com/photos/straup/2971287541/"><img decoding="async" src="http://farm4.static.flickr.com/3288/2971287541_27e6a06a21_m.jpg" style="border:none;" /></a></td> <td width="5%;">&nbsp;</td> <td><a href="http://flickr.com/photos/straup/2972131146/"><img decoding="async" src="http://farm4.static.flickr.com/3067/2972131146_92c785b00c_m.jpg" style="border:none;" /></a></td> </tr> </table> <p>Even neighbourhoods:</p> <table> <tr> <td><a href="http://flickr.com/photos/straup/2972131416/"><img decoding="async" src="http://farm4.static.flickr.com/3254/2972131416_3d2256360e_m.jpg" style="border:none;" /></a></td> <td width="5%;">&nbsp;</td> <td><a href="http://flickr.com/photos/straup/2986628225/"><img decoding="async" src="http://farm4.static.flickr.com/3166/2986628225_f1c3e1c39c_m.jpg" style="border:none;" /></a></td> </tr> </table> <p>Each one of those illustrations represents the boundaries of a particular place whose outline was generated using <strong>nothing but the latitudes and longitudes of the geotagged photos associated with that location&#8217;s WOE ID</strong>. No <a href="http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> information was harmed in the creation of these shapes.</p> <p><em>How cool is that?!</em></p> <h2 style="margin-bottom:15px;">How does it work?</h2> <p>The short version is: Scary and complicated maths. The longer version is: We are generating <a href="http://biogeometry.duke.edu/software/alphashapes/index.html">alpha shapes</a> using the set of unique latitudes and longitudes associated with a WOE ID. The long version, to quote <a href="http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Alpha_shapes_3/Chapter_main.html">Tran Kai Frank Da and Mariette Yvinec</a>, is:</p> <blockquote style="font-family:sans-serif; margin-left:10%;margin-right:10%;"> <p>&#8220;Imagine a huge mass of ice-cream making up the space &#8230; and containing the points as <q>hard</q> chocolate pieces. Using one of those sphere-formed ice-cream spoons we carve out all parts of the ice-cream block we can reach without bumping into chocolate pieces, thereby even carving out holes in the inside (eg. parts not reachable by simply moving the spoon from the outside). We will eventually end up with a (not necessarily convex) object bounded by caps, arcs and points. If we now straighten all <q>round</q> faces to triangles and line segments, we have an intuitive description of what is called the alpha shape&#8230;&#8221;</p> </blockquote> <p>(There are also some useful illustrations of what that all means on Francois Belair&#8217;s <a href="http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/alpha.html"> Everything You Always Wanted to Know About Alpha Shapes But Were Afraid to Ask</a> website.)</p> <h2 style="margin-bottom:15px;">The community of authority and the authority of community</h2> <p>This is the important part: Many, if not most, of these shapes will look a little weird. Possibly even &#8220;wrong&#8221;. This is both okay and to be expected for a few reasons, at least.</p> <ul> <li> <p>Sometimes we just don&#8217;t have enough geotagged photos in a spot to make it is possible to create a shapefile. Even if we do have enough points to create a shape there aren&#8217;t enough to create a shape that you&#8217;d recognize as the place where you live. We chose to publish those shapes anyway because it shows both what we know and don&#8217;t about a place and to encourage users to help us fix mistakes.</p> <p>If the shape of the neighbourhood is incomplete or looks weird why not consider organizing a <a href="http://www.flickr.com/photos/tags/photowalk/map">photowalk</a> around its edges and when you get home add them to the map. The next time we generate a new shapefile for that neighbourhood it should look more like the place you recognize!</p> </li> <li> <p>We did a bad job reverse geocoding photos for a particular spot and they&#8217;ve ended up associated with the wrong place. We&#8217;ve learned quite a lot about how to do a better job of it in the last two years but there is a limit to how much human awareness and subtlety we can codify. Sometimes, the data we have to try and work out what&#8217;s going on is just bad or out of date.</p> <p>Ultimately, that&#8217;s why we added <a href="http://code.flickr.com/blog/2008/08/08/location-keeping-it-real-on-the-streets-yo/">the tools to help users correct their geotagged photos</a> so that we can adjust things to their understanding of the world and begin to map facts on the ground rather than from on high.</p> </li> <li> <p>We are not very sophisticated yet in how we assign the size of the alpha variable when we generate shapes. As far as we can tell no one else has done this sort of thing so like reverse-geocoding we are learning as we go. For example, with the exception of continents and countries we boil all other places down to a single contiguous shape. We do this by slowly cranking up the size of the ice cream scoop which in turn can lead to a loss of fidelity.</p> <p>Does the <q>shape</q> of Florida, or of Italy, include the waters that lie between the mainland and the surrounding islands? It&#8217;s not usually the way we imagine the territory that a place occupies but I think it probably does. On the other hand, including the ocean between California and Hawaii as <q>part of</q> the United States would be kind of dumb.</p> </li> <p>Are any of these the correct decisions? We&#8217;re not sure yet.</p> </li> </ul> <p>A concrete example to illustrate the point. Here are two versions of the island of <a href="http://www.flickr.com/places/Canada/Quebec/Montreal">Montreal</a>, each generated from the same set of coordinates. The version on the left used an alpha number (an ice cream spoon) large enough to ensure that only a single shape was created compared with the version on the right that allowed for two shapes.</p> <table> <tr> <td><img decoding="async" src="http://farm4.static.flickr.com/3189/2972131778_d6d2b9a629_m.jpg" /></td> <td width="5%;">&nbsp;</td> <td valign="top"><img decoding="async" src="http://farm4.static.flickr.com/3031/2986660583_6f6bd6f113_m.jpg" width="240" height="181" alt="" /></td> </tr> </table> <p>What&#8217;s going on, then? All those photos taken in St. Jean-sur-Richelieu (20 minutes south of Montreal) were added to the map back when we first added geotagging to the site and the information about the province of Quebec was not as detailed as what we have now. Ultimately, we decided to include the version on the left because as <a href="http://magicalnihilism.wordpress.com/2008/10/11/bionic-noticing-on-irving-street/">Matt Jones recently said</a>:</p> <blockquote style="font-family:sans-serif; margin-left:10%;margin-right:10%;"> <p>&#8220;<em>The long here</em> that Flickr represents back to me is becoming only more fascinating and precious as geolocation starts to help me understand how I identify and relate to place. The fact that Flickr&#8217;s mapping is now starting to <a href="http://code.flickr.com/blog/2008/09/04/whos-on-first/">relate location to me the best it can in human place terms</a> is fascinating &#8211; they do a great job, but where it falls down it falls down gracefully, inviting corrections and perhaps <a href="http://www.flickr.com/photos/blackbeltjones/2920892513/#comment72157607816350512">starting conversation</a>.&#8221;</p> </blockquote> <p>As with any visualization of aggregate data there are likely to be areas of contention. One of the reasons we&#8217;re excited to make this stuff available is that much of it simply isn&#8217;t available anywhere else and the users and the developer community who make up Flickr have a gift for building magic on top of the API so we&#8217;re doubly-excited to see what people do with it.</p> <p>That said please remember that this it is an aggregate view of things and should be treated more like the <a href="http://www.flickr.com/places/US/CA/SF#zeitgeist">the zeitgeist of a place</a> and not as capital-C confirmed facts on the ground or our taking sides in any conflicts (real, imagined or otherwise) between friends and neighbours.</p> <p>These are not maps you should use to guide your spaceship back to Earth but they&#8217;re probably good enough to explore the possibilities.</p> <h2 style="margin-bottom:15px;">Clustr</h2> <div style="margin-top:20px;margin-bottom:20px;"> <a href="http://flickr.com/search/?w=all&#038;q=schuyler+erle&#038;m=text" title="UR DOTZ I HAS DEM"><img decoding="async" src="http://farm4.static.flickr.com/3252/2985372999_dc8fca06e2.jpg" width="500" height="375" alt="UR DOTZ I HAS DEM" style="border:1px dotted #ccc;padding:10px;" /></a> </div> <p>Meanwhile, back in the nuts-and-bolts department: The actual alpha shapes are generated by a program called Clustr, written for us by <a href="http://iconocla.st/cv.html">the fantabulous Schuyler Erle</a>.</p> <p>Clustr is a command-line application written in C++ that takes as its arguments the path to a file containing a list of points (the hard chocolate pieces) and an alpha parameter (the ice cream spoon) and generates a <a href="http://en.wikipedia.org/wiki/Shapefile">shapefile</a> describing the contour (the alpha shape) of that list. Anecdotally, we&#8217;ve seen Clustr plow through a file with four million unique coordinates (representing the continental United States, Alaska and Hawaii) in under three minutes on some pretty modest hardware.</p> <p>The shapedata for a WOE ID is available via the Flickr API using the <a href="http://www.flickr.com/services/api/flickr.places.getInfo.html">flickr.places.getInfo</a> method.</p> <p>Not all places have shape data yet so the root &lt;place&gt; element contains a <code>has_shapedata</code> attribute for checking at a glance. Otherwise you can test for the presence of a &lt;shapedata&gt; element. It will look like this:</p> <pre> &lt;place place_id=&quot;4hLQygSaBJ92&quot; woeid=&quot;3534&quot; latitude=&quot;45.512&quot; longitude=&quot;-73.554&quot; place_url=&quot;/Canada/Quebec/Montreal&quot; place_type=&quot;locality&quot; name=&quot;Montreal, Quebec, Canada&quot; <strong>has_shapedata=&quot;1&quot;</strong>&gt; &lt;!-- all the usual places hierarchy elements --&gt; <strong>&lt;shapedata created=&quot;1223513357&quot; alpha=&quot;0.012359619140625&quot; count_points=&quot;34778&quot; count_edges=&quot;52&quot;&gt; &lt;polylines&gt; &lt;polyline&gt; 45.427627563477,-73.589645385742 45.428966522217,-73.587898254395, etc... &lt;/polyline&gt; &lt;/polylines&gt; &lt;/shapedata&gt;</strong> &lt;/place&gt; </pre> <p style="text-decoration:line-through;">Sometime next week, we will also include links to a real live <a href="http://en.wikipedia.org/wiki/Shapefile">ESRI shapefile</a>, the well-known and mostly-loved lingua franca of the GIS community, for each WOE ID. They were supposed to be included with this release but because of a last minute glitch they need to be prettied up a little first. We think that the inclusion of the polylines will be enough to keep people busy until then. Shapefiles will be included, in the API, as a link to a compressed file you can download separately. For example:</p> <p style="font-style:italic;">Update: The first round of (ESRI) <a href="http://en.wikipedia.org/wiki/Shapefile">shapefiles</a> have been reprocessed and are now available via the API. Shapefiles are included as a link to a compressed file you can download separately. For example:</p> <pre> &lt;urls&gt; <strong>&lt;shapefile&gt; http://farm4.static.flickr.com/9999/shapefiles/3534_20081020_S33KR3TSHAPE.tar.gz &lt;/shapefile&gt;</strong> &lt;/urls&gt; </pre> <p>Our plan is to generate new renderings on a relatively constant basis, something like every month or two, though we haven&#8217;t firmed up any of those details yet. We&#8217;ll post about them here or on the <a href="http://tech.groups.yahoo.com/group/yws-flickr/">API mailing list</a> as things are worked out.</p> <h2 style="margin-bottom:15px;">But wait, there&#8217;s more!</h2> <p>Along with the shape data the source code for Clustr is available in the Flickr Code <a href="http://code.flickr.com/svn/trunk/clustr/">repository</a> and through <a href="http://code.flickr.com/trac/browser/trunk/clustr">our trac install</a>, distributed under the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GPL (version 2)</a>.</p> <p>Clustr has two major dependencies not included with the source that you will need to install yourself in order to use. They are the <a href="http://www.cgal.org/">Computational Geometry Algorithms Library</a> (CGAL) and the <a href="http://www.gdal.org/">Geospatial Data Abstraction Library</a> (GDAL). Both are relatively straightforward to install on <a href="http://packages.ubuntu.com/">Linux</a> and <a href="http://www.freshports.org/">BSD</a> flavoured operating systems; Windows and OS X are still a bit of a chore.</p> <p>You probably won&#8217;t be able to download Clustr and simply plug it in to your awesome web-application today but I am hopeful that in time the community will develop higher level language (Perl, Python, Ruby, you name it&#8230;) bindings to make it easier and faster to write tools that build on the work we&#8217;ve done so far.</p> <div style="margin-top:20px;margin-bottom:20px;"> <a href="http://flickr.com/photos/julianbleecker/2787751572/"><img decoding="async" src="http://farm4.static.flickr.com/3215/2787751572_c4a74415d6.jpg" style="border:1px dotted #ccc;padding:10px;" /></a></p> <p style="font-size:small;">photo by <a href="http://flickr.com/photos/julianbleecker/">Julian Bleecker</a></p> </div> <p style="text-decoration:line-through;">By the way, there is a still a known-known bug in Clustr rendering <q>interior rings</q> (the donut holes where there are no geotagged photos) in shapefiles. Specifically, they holes are rendered as actual polyline records. You can see an example of the problem in the screenshot of the shapefile for North America, above. We hope to have a proper patch in place by the time we make the ESRI files available next week. As it is since the problem only manifests itself for countries and continents it seemed like a reasonable thing for a version 0.1 release.</p> <p style="font-style:italic;">Update: Clustr 0.2, with a fix for <a href="http://code.flickr.com/trac/changeset/461">errant interior rings</a>, has been checked in to the <a href="http://code.flickr.com/svn/trunk/clustr/">code.flickr.com SVN repository</a>.</p> <p>Finally, these are early days and this is very much a developer&#8217;s release so we look forward to your feedback and also hope you will be understanding as we learn our way around the gotchas and quirks that will no doubt pop up.</p> <h2 style="margin-bottom:15px;">In other geostuffs</h2> <p>In other geostuffs, we have enabled Open Street Maps tiles for two more cities: Baghdad and Kabul and George has written <a href="http://flickrtheblog.wordpress.com/2008/10/30/more-cities/">a fantastic post highlighting some of the photos we&#8217;ve found in both cities</a> so go and have a look.</p> <div style="margin-top:20px;margin-bottom:20px;"> <a href="http://www.flickr.com/photos/straup/2987745074/" title="Picture 16 by straup, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3035/2987745074_9acfe83c68_o.png" width="488" height="486" alt="Picture 16" style="border:1px dotted #ccc;padding:10px;" /></a> </div> <p><small>Map data <a href="http://creativecommons.org/licenses/by-sa/3.0/">CCBYSA</a> 2008 <a href="http://OpenStreetMap.org">OpenStreetMap.org</a> contributors</small></p> <p>Enjoy!</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/geo/" rel="category tag">geo</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/clustr/" rel="tag">clustr</a>, <a href="https://code.flickr.net/tag/geo/" rel="tag">geo</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-278 --> <article id="post-274" class="post-274 post type-post status-publish format-standard hentry category-uncategorized"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/30/krazydad-sunrise-sunset/" rel="bookmark">KrazyDad 禄 Sunrise, Sunset</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/30/krazydad-sunrise-sunset/" title="2:53 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-30T14:53:33-07:00">October 30, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p><a href="http://www.krazydad.com/">KrazyDad</a> who <a href="http://code.flickr.com/blog/2008/10/14/5-questions-for-jim-bumgardner/">kicked off our developer 5 questions series</a> the other week, has a <a href="http://www.krazydad.com/blog/2008/10/29/sunrise-sunset/">post up</a> looking at animated visualizations of sunset and sunrise. </p> <blockquote><p><i>If you pay close attention to the differences between the two photos, particularly Florida and the Great Lakes, you鈥檒l see that people prefer to photograph the sun sinking (or rising) behind a body of water. Hence eastern-facing coastlines tend to accumulate more sunrise photos, and western-facing coastlines tend to accumulate sunset photos.</i> &#8211; <a href="http://www.krazydad.com/blog/2008/10/29/sunrise-sunset/">KrazyDad &raquo; Sunrise, Sunset</a></p></blockquote> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-274 --> <article id="post-266" class="post-266 post type-post status-publish format-standard hentry category-uncategorized"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/27/counting-timing/" rel="bookmark">Counting &#038; Timing</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/27/counting-timing/" title="10:24 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-27T22:24:11-07:00">October 27, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>Here at Flickr, we&#8217;re pretty nerdy. We like to measure stuff. We <i>love</i> measuring stuff. The more stuff we can measure, the better our understanding of how different parts of the website work with each other gets. There are two types of measurement we especially like to do &#8211; counting and timing. These exciting activities help us to know what is happening when things break &#8211; if a page is taking a long time to load, where is that time being spent and what task have we started to do more of.</p> <h3>Counting</h3> <p>Our best friend, when it comes to stats collection and display is <a href="http://oss.oetiker.ch/rrdtool/">RRDTool</a>, the Round-Robin Database. RRD is a magical database that uses a fixed amount of space for storing stats over time. It does this by storing data in decreasingly lower resolution as time goes by, keeping high resolution per-minute data for the last few hours, a lower per-day resolution data for times last year (the resolution is actually configurable). Since you generally care less about detailed data in the past, this works really well. RRD typically works in two modes &#8211; you feed it a number every so often and that number can either be a gauge (such as the current temperature) or a counter (such as the number of packets sent through a switch port). Gauges are easy, but RRD is clever enough to know how counters change over time. It then lets you graph these data points in interesting ways.</p> <p><a href="http://www.flickr.com/photos/bees/2979350706/" title="Counter - Basic RRD by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3148/2979350706_6f6b5ca133.jpg" width="500" height="184" border="0" alt="Counter - Basic RRD" /></a></p> <p>The problem with RRD is that you often want to count some kind of event that doesn&#8217;t have a natural counter associated with it. For instance, we might want to count how many times we connect to a certain cache server from a particular piece of code, so that we can graph it. We know when we connect to it in the code, but there&#8217;s no global number tracking that count. We need some central counter which we increment each time we connect, which we can then periodically feed into RRD. This tends to get quickly further complicated by having multiple machines on which the code runs &#8211; every one of Flickr&#8217;s web servers will run this code, but we care about how many times they connect to the cache server <i>in total</i>.</p> <p>The easiest way to do this is to use a database. When we connect to the cache server, connect to the database and increment a counter. Some other job can then periodically connect to the database, read the counter and store it in RRD. Simple! However, the operation of connecting to the database and performing the write does not have zero cost. It takes some amount of time which may appear trivial at first, but doing that several hundred times a second (lots of the operations we want to track happen very often), multiplied by hundreds of different things we want to track quickly adds up. It&#8217;s a little bit quantum theory-ish &#8211; the act of observing changes the observed reality. When we&#8217;re counting very fast operations, we can&#8217;t spend much time on the counting.</p> <p>There&#8217;s luckily an operation which we can perform that&#8217;s cheap enough to do very often while allowing us to easily collect data from multiple servers at once: <a href="http://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a>. The User Datagram Protocol is TCP&#8217;s ugly kid brother. Unlike TCP, UDP does not guarantee delivery of packets, nor the order in which they&#8217;ll be received. In return, they&#8217;re a lot faster to send and use less bandwidth. When counting frequent stats, losing the odd packet doesn&#8217;t really hurt us, especially when we can also graph when we&#8217;ve been dropping packets (under Linux, try <code>netstat -su</code> and look for &#8220;packet receive errors&#8221;). Changing the UDP buffer size (kernel variable <code>net.core.rmem_max</code>) allows you to queue more packets before processing them, if you find you can&#8217;t keep up.</p> <p>In our client code, this is very easy to do. Every language has a different approach (of course!), but they&#8217;re all straight forward.</p> <h4>Perl</h4> <pre style="margin-bottom: 1em"> my $sock = new IO::Socket::INET( PeerAddr => $server, PeerPort => $port, Proto => 'udp', ) or die('Could not connect: $!'); print $sock "$valuen"; close $sock; </pre> <h4>PHP</h4> <pre style="margin-bottom: 1em"> $fp = fsockopen("udp://$server", $port, $errno, $errstr); if ($fp){ fwrite($fp, "$valuen"); fclose($fp); } </pre> <p>The trickier part is the server component. We need something that will receive packets, increment counters and periodically save the counter to RRD files. At Flickr we developed a small Perl daemon to do this, using an alarm to save the counters to RRD. The UDP packet simply contains the name of the counter to increment. We can then start to track interesting operations over time:</p> <p><a href="http://www.flickr.com/photos/bees/2979295274/" title="Counter - Simple by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3160/2979295274_a42b808902.jpg" width="500" height="309" border="0" alt="Counter - Simple" /></a></p> <p>The next stage was to change our simple counters into ones which recorded state. We&#8217;re performing a certain operation 300 times a second, but how often is it failing? RRD allows you to store multiple counters in a single file and then graph them together in a variety of ways, so all we needed was a little modification to our collection daemon.</p> <p><a href="http://www.flickr.com/photos/bees/2978443355/" title="Counter - Failures by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3201/2978443355_37d8298c2a.jpg" width="500" height="78" border="0" alt="Counter - Failures" /></a></p> <p>The red area on the left shows some failures. Some tasks have very few relative failures, but which are still important to see. That&#8217;s easy enough, but just producing two graphs with different Y-axis scales (something that RRD does auto-magically for us).</p> <p><a href="http://www.flickr.com/photos/bees/2978444771/" title="Counter - Small Failures by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3163/2978444771_7537242aa2.jpg" width="500" height="175" border="0" alt="Counter - Small Failures" /></a></p> <h3>Timing</h3> <p>Counting the number of times we perform a certain task can tell us a lot, but often we&#8217;ll want to know how long that task took. The simplest way to do this is to perform a task periodically and graph the result. This is pretty simple and something that we use <a href="http://code.flickr.com/blog/2008/10/13/flickr-digs-ganglia/">Ganglia</a> for to good effect.</p> <p><a href="http://www.flickr.com/photos/bees/2978462971/" title="Timings - Simple by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3008/2978462971_1abd35a1ff.jpg" width="500" height="194" border="0" alt="Timings - Simple" /></a></p> <p>The problem with this is that it just tells us the time it took to perform our single test task. This is useful for looking at macro problems, but is useless against tasks that can take a variable amount of time. If a database server is processing one in ten tasks slowly, then that will appear on this graph as a spike (roughly) every ten samples &#8211; it&#8217;s impossible for us to tell the different between a server that processes 10% of requests slowly and a sever that has periodic slow periods. We could take an average time (but storing an accumulator along with the counter, and dividing at the end of each period) and this gets us closer to useful data.</p> <p>What we really need to know, however, is something like our standard deviation &#8211; both what our average is and where the bulk of our samples lie. This allows us to distinguish between a request that always takes 20ms and one that takes 10ms half of the time and 30ms half of the time. To achieve this, we changed our collection daemon to keep a list of timings. At the end of each sampling period (somewhere between 10s and 60s, depending on the thing we&#8217;re monitoring), we then sort these times, find the mean and the first and third <a href="http://en.wikipedia.org/wiki/Quartiles">quartiles</a>. By storing each of these values (along with a min and max) into RRD every period, we can show the average timing along with the tolerance.</p> <p><a href="http://www.flickr.com/photos/bees/2979313068/" title="Timings - Quartiles by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3286/2979313068_2c20ccdd88.jpg" width="500" height="217" border="0" alt="Timings - Quartiles" /></a></p> <p>So our task takes 250ms on average, with 75% finishing within ~340ms and 25% finishing within ~190ms. The light green shaded area shows the lowest 25%. We don&#8217;t shade the upmost 25%, since random spikes can cause the Y-axis to become to large that it makes the graph difficult to read. We don&#8217;t have this problem with the lowest quartile, since nothing can be faster than zero (and we always show zero on the Y-axis to avoid scale bias).</p> <h3>Bringing it all together</h3> <p>The next step is to tie together the counting with the timing, to allow us to see how the rate of an operation effected the time which it took to perform. By simply lining up graphs below each other, we can easily see relationships between these different measures:</p> <p><a href="http://www.flickr.com/photos/bees/2978453229/" title="Timings - Correlate Simple by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3241/2978453229_068cb4421a.jpg" width="500" height="304" border="0" alt="Timings - Correlate Simple" /></a></p> <p>Of course, we like to go a little measurement-crazy, so we tend to sample as many things as we can to look for patterns. This graph from our <a href="http://code.flickr.com/blog/2008/09/26/flickr-engineers-do-it-offline/">Offline Task System</a> shows how often we run a particular task, how long it took to execute but also how long it was queued before we ran it.</p> <p><a href="http://www.flickr.com/photos/bees/2979305994/" title="Timings - Correlate by bees, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3162/2979305994_5deb549cd8.jpg" width="500" height="419" border="0" alt="Timings - Correlate" /></a></p> <p>The code for out timing daemon is available in the Flickr Code <a href="http://code.flickr.com/svn/trunk/Flickr-StatsD/">repository</a> and through <a href="http://code.flickr.com/trac/browser/trunk/Flickr-StatsD">our trac install</a>, so you can have a play with it yourself. It just requires RRDTool and some patience. Get graphing!</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-266 --> <article id="post-239" class="post-239 post type-post status-publish format-standard hentry category-uncategorized tag-css tag-javascript tag-mobile tag-optimization"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/27/lessons-learned-while-building-an-iphone-site/" rel="bookmark">Lessons Learned while Building an iPhone Site</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/27/lessons-learned-while-building-an-iphone-site/" title="3:35 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-27T15:35:37-07:00">October 27, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/rharmes/" title="View all posts by Ross Harmes" rel="author">Ross Harmes</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3286/2969952478_0e0aeb21c2_o.png" width="207" height="385" alt="The Explore Page in the iPhone site" style="float:right; margin: 0 0 10px 10px;" /></p> <p>A few weeks ago we released a version of the Flickr site tailored specifically for the iPhone. Developing this site was very different from any other project I&#8217;ve worked on; there seems to be a new set of frontend rules for developing high-end mobile sites. A lot of the current best practices get thrown out the window in the quest for minimum page weight and fastest load times over slow cellular connections.</p> <p>Here are a few of the lessons we learned (sometimes painfully) while developing this site.</p> <p><b>1. Don&#8217;t Use a JavaScript Library or CSS Framework</b></p> <p>This was one of the hardest things for me to come to terms with. I&#8217;m a huge fan of libraries, especially <a href="http://developer.yahoo.com/yui/">YUI</a>, mostly because they allow me to spend my time creating new stuff instead of working around crazy browser quirks. But these libraries walk a fine line; by definition, they must work across a wide array of browsers and offer enough features to make them worth using. This means they potentially contain a lot of code that you don&#8217;t care about and won&#8217;t use. This code is dead weight to your site.</p> <p>With such a high percentage of normal web users on broadband connections, we&#8217;ve gotten cavalier about what we can include in our pages. 250 KB of JavaScript or more isn&#8217;t uncommon for a large site these days. But for sites that are meant to be viewed over slow cellular connections like EDGE, 250 KB is an impossible amount of data. The only way to get the size of your JavaScript down is to selectively pull code out of libraries, and include only what you use. This means you can rip out code meant only for browsers that you won&#8217;t support (modular libraries like the new <a href="http://developer.yahoo.com/yui/3/">YUI 3.0</a> allow you to only include the code you use, preventing this problem somewhat).</p> <p>The same goes for CSS. Frameworks make development faster and your final product more robust, but they, like the JavaScript libraries, include code for situations you won&#8217;t have to deal with. Every line in your CSS <b>must</b> be custom; each property must be scrutinized to ensure it&#8217;s needed.</p> <p><b>2. Load Page Fragments Instead of Full Pages</b></p> <p><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3285/2969107023_e299521717_o.png" width="510" height="291" alt="Loading fragments saves 92.2% of the page size"></p> <p>When navigating through a site, most of what changes from page to page is the actual content; the JavaScript, CSS, header and footer stay mostly the same. We can use this to our advantage by only loading the part of each page that changes. We did this by hijacking all links of the page: when a link is clicked, we intercept the event, fetch the page fragment using Ajax, and insert the HTML into a new div. This has several benefits:</p> <ul style="font-size:108%;line-height:150%;margin-bottom:1em;"> <li style="margin-bottom:4px;">Since you control the entire life cycle of the page fetch, you can display loading indicators or a wireframe version of the page while new pages load</li> <li style="margin-bottom:4px;">All pages that have been fetched will exist within the DOM; clicking the back button (or clicking on a link for a page that has already been fetched) results in an instantaneous page load</li> <li style="margin-bottom:4px;">The page fragments are extremely small; ours are about 800 bytes (gzipped) on average</li> </ul> <p>Using this system complicates your code a bit. You need JavaScript to handle the hijacking, the page fragment insertion, and the address bar hash changes (which allow the back and forward buttons to work normally). You also need your backend to recognize requests made with Ajax, and to only send the page content instead of the full HTML document. And lastly, if you want normal URLs to work, and each of your pages to be bookmarkable, you will need even more JavaScript. </p> <p>Despite these downsides, the benefits can&#8217;t be ignored. The extra JavaScript code is a one-time cost, but the extra page content that we would have downloaded is saved for <i>every page load</i>. We found it was worth the complication and additional JS in order to dramatically reduce the time it took to load each page.</p> <p><b>3. Don&#8217;t Build for Just One Device</b></p> <p>It&#8217;s really tempting to build the site for just the iPhone: you can use modern CSS (including things like CSS3 selectors and transformations), you don&#8217;t have to hack around annoying browser quirks, and testing is extremely easy. But any single device, even one as ubiquitous as the iPhone, has a limited share of the mobile market, especially internationally. Rarely can you justify the cost of creating a one-off site for a very small number of your users.</p> <p>Luckily the current generation of high-end mobile browsers is excellent in terms of support for modern features. Many phones use a <a href="http://webkit.org/">WebKit</a> derivative, including the iPhone, and Symbian and Android phones. Other phones either come with or can use <a href="http://www.opera.com/products/mobile/">Opera Mobile</a> or the new mobile version of Firefox (called <a href="http://starkravingfinkle.org/blog/2008/10/fennec-m9-user-experience-alpha/">Fennec</a>). For the most part, very few changes are needed in order to support these browsers.</p> <p>Most of the differences lie in layout. It&#8217;s important to structure your pages around a grid that can expand as a percentage of the page width. This allows your layouts to work on many different screen sizes and orientations. The iPhone, for example, allows both landscape and portrait viewing styles, which have vastly different layout requirements. By using percentages, you can have the content fill the screen regardless of orientation. Another option is to detect viewport width and height, and use JavaScript to dynamically adjust classes based on those measurements (but we found this was overkill; CSS can handle most situations on its own).</p> <p><b>4. Optimize <i>Everything</i> </b></p> <p>The browsers on mobile devices operate under much stricter constraints than their desktop cousins. Slower CPUs, smaller amounts of memory, and smaller hard drives mean that less data can be cached. On the iPhone, for instance, only files smaller than 25 KB are cached. This puts very specific limits of the size of your files. For a large site like Flickr, 25 KB worth of JavaScript and CSS barely scratches the surface. To put our files under the limit, we ran everything through the <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> using the most aggressive settings. We ran all images through compression tools as well (we like <a href="http://advsys.net/ken/utils.htm">pngout</a> and <a href="http://smushit.com/">Smushit</a>), reducing each image file by an average of 40%. We also made heavy use of sprites, where possible.</p> <p>In the end, we were able to go from 90+ second load times over EDGE to less than 7 for an empty cache experience. Using page fragments, we are able to load and display new pages in under a second (though the images in those pages take longer to load). These are not trivial gains, and make the difference between a good mobile experience and a one that is so awful the user gives up halfway through the page load.</p> <p><b>5. Tell the User What is Happening</b></p> <p>Once we hijacked all clicks actions in order to load page fragments, it wasn&#8217;t always clear to the user if anything was happening when they clicked on a link. This is especially true on touch devices, where it is difficult to know if the device even detected your action. To combat this problem, we added loading indicators to every link. These tell the user that something is happening, and reassures them that their action was detected. It also makes the pages seem to load much faster, since something is happening right away; if the indicators weren&#8217;t there, it would seem like nothing was happening for a few seconds, and then the page would load suddenly. In our testing, these indicators were the difference between a UI that seems snappy and responsive, and one that seemed slow and inconsistent.</p> <p style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3274/2969106971_2b4166f943_o.png" width="382" height="99" alt="Loading indicators" /></p> <p><b>One Easy Option</b></p> <p>The <a href="http://code.google.com/p/iui/">iUI framework</a> implements a lot of these practices for you, and might be a good place to start in developing any mobile site (though keep in mind it was developed specifically for the iPhone). We found it especially useful in the early stages of development, though eventually we pulled it out and wrote custom code to run the site.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/css/" rel="tag">css</a>, <a href="https://code.flickr.net/tag/javascript/" rel="tag">javascript</a>, <a href="https://code.flickr.net/tag/mobile/" rel="tag">mobile</a>, <a href="https://code.flickr.net/tag/optimization/" rel="tag">optimization</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-239 --> <article id="post-213" class="post-213 post type-post status-publish format-standard hentry category-kittens tag-kittentuesday"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/21/kitten-tuesday-ascii-edition/" rel="bookmark">Kitten Tuesday, ASCII Edition</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/21/kitten-tuesday-ascii-edition/" title="1:40 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-21T13:40:40-07:00">October 21, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> <div class="comments-link"> <a href="https://code.flickr.net/2008/10/21/kitten-tuesday-ascii-edition/#respond"><span class="leave-reply">Reply</span></a> </div> </header><!-- .entry-header --> <div class="entry-content"> <p><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3237/2962626876_3d3ce2b1c6_o.jpg" width="470" height="687" alt="Flickr Asciified - Nihilogic" /></p> <p>Jason over at Nihilogic has a post up called <a href="http://blog.nihilogic.dk/2008/10/getting-your-ascii-on-with-flickr.html">Getting your ASCII on with Flickr</a> &#8230;</p> <blockquote><p><i>&#8220;You simply enter the search query of your choice and click the &#8220;Asciify&#8221; button. A request is then sent off to the Flickr server and any photos that match the query are returned. The image data is analyzed and turned into ASCII characters.&#8221;</i></p></blockquote> <p>Obviously I made a Kitten and you too can get flickrasciified over <a href="http://www.pixastic.com/labs/flickr_asciified/">here</a>.</p> <p><a href="http://www.flickr.com/photos/66036063@N00/2353322369/">Orginal Photo</a> by <a href="http://www.flickr.com/photos/paulesson/">pontman</a>.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/kittens/" rel="category tag">kittens</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/kittentuesday/" rel="tag">kittentuesday</a> </span> <span class="sep"> | </span> <span class="comments-link"><a href="https://code.flickr.net/2008/10/21/kitten-tuesday-ascii-edition/#respond"><span class="leave-reply">Leave a reply</span></a></span> </footer><!-- .entry-meta --> </article><!-- #post-213 --> <article id="post-217" class="post-217 post type-post status-publish format-standard hentry category-uncategorized"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/20/a-little-about-the-flickr-bike/" rel="bookmark">A Little About The Flickr Bike</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/20/a-little-about-the-flickr-bike/" title="7:52 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-20T19:52:17-07:00">October 20, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> <div class="comments-link"> <a href="https://code.flickr.net/2008/10/20/a-little-about-the-flickr-bike/#respond"><span class="leave-reply">Reply</span></a> </div> </header><!-- .entry-header --> <div class="entry-content"> <p><div><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.30" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=9645302&#038;vid=3472740&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/yahoopurple/4674/71286477.jpg&#038;embed=1" /></object><br /><a href="http://video.yahoo.com/watch/3472740/9645302">A sum of its parts</a> @ Yahoo! Video (for ppl using RSS readers)</div> <p></a></p> <p><a href="http://flickr.com/photos/shanan/">Shanan&#8217;s</a> been driving me insane riding the <a href="http://www.flickr.com/photos/flickrhq_bike/">Flickr Bike</a> around the office. If you don&#8217;t know about the Flickr Bike, in a nutshell we have 20 purple bikes tricked out with Nokia N95s geotagging photos and uploading them to Flickr (of course) as people cycle round, there&#8217;s a video (<a href="http://news.cnet.com/1606-1_3-50003781.html">Flickr&#8217;s handlebar cameras</a>) over on cnet, and a frankly awesome write up on <a href="http://lifehacker.com/5049737/flickr-bikes-photo+map-locales-across-the-globe">Lifehacker</a>.</p> <p>This being the Dev Blog we&#8217;re interested in looking under the hood, to use an awful metaphor, and finding out how things work. Fortunately for us Josh wrote up a blog post last week, including links to source code and all that good stuff, meaning I can simple point to that, Huzzah for the internet!</p> <h3><b>Read techy stuff over at ~~> <a href="http://www.uncommonprojects.com/uplog/2008/10/14/coding-a-networked-bike/">Coding a Networked Bike</a></b></h3> <p>If you&#8217;re more of a moving pictures with sounds than words person, then Lifehacker has 6 videos up that are worth a watch: <a href="http://lifehacker.com/5049738/the-making-of-the-flickr-bikes">The Making of the Flickr Bikes</a>. The seconds one of which I included at the start of this blog post.</p> <p>Oh and fyi, they&#8217;re Electra bikes painted #7B0099 (Pantone 2602 C).</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="comments-link"><a href="https://code.flickr.net/2008/10/20/a-little-about-the-flickr-bike/#respond"><span class="leave-reply">Leave a reply</span></a></span> </footer><!-- .entry-meta --> </article><!-- #post-217 --> <article id="post-194" class="post-194 post type-post status-publish format-standard hentry category-uncategorized tag-5questions tag-api tag-interview tag-people tag-software tag-tools"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/14/5-questions-for-jim-bumgardner/" rel="bookmark">5 Questions for Jim Bumgardner</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/14/5-questions-for-jim-bumgardner/" title="10:09 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-14T22:09:58-07:00">October 14, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>We&#8217;ve been keeping a careful eye on our <a href="http://blog.flickr.com">Sister Blog</a> to see what they&#8217;re up to. Something that&#8217;s particularly caught our eye is &quot;<a href="http://blog.flickr.net/en/2008/09/11/5-questions-lomokev/">5 Questions</a> &quot;, asking the same 5 questions to the Flickrverse, with the last question being who we should ask next. And so, we hope, it goes on and on.</p> <p><a title="Banana-bub by krazydad / jbum, on Flickr" href="http://www.flickr.com/photos/krazydad/60145421/" title="Banana-bub by krazydad / jbum, on Flickr"><img loading="lazy" decoding="async" style="float: right; margin-left: 20px; margin-bottom: 10px;" src="http://farm1.static.flickr.com/33/60145421_3093f5e164_m.jpg" alt="Banana-bub" width="180" height="240" /> </a></p> <p>This is our version, asking questions of those that develop, hack and fiddle with Flickr in new and interesting ways. Of course we couldn&#8217;t start with anyone else but <a href="http://flickr.com/photos/krazydad/">KrazyDad</a> (aka Jim Bumgardner).</p> <p>Jim founded the <a href="http://www.flickr.com/groups/flickrhacks/">Flickr Hacks</a> group back in the day, a great place to hang out and ask question if you want to learn how to bend Flickr to your will. In 2006 he also coauthored the <a href="http://www.amazon.com/exec/obidos/ASIN/0596102453">Flickr Hacks</a> book for O&#8217;Reilly and happily for us he hasn&#8217;t stopped tinkering with Flickr yet.</p> <p>So, without any further ado, 5 Questions for Jim Bumgardner:</p> <p><b>1. What are you currently building that integrates with Flickr, or a past favorite that you think is cool, neat, popular and worth telling folks about? Or both.</b></p> <p><i>Jim:</i> It seems like I&#8217;m always building something that integrates Flickr. A recent favorite is this interactive mosaic that shows the most interesting photos of the week.</p> <p>The photos are arranged to form a spiral, a form that appears quite frequently in my work.</p> <p><a href="http://www.coverpop.com/pop/flickr_interesting">www.coverpop.com/pop/flickr_interesting</a><br /> <a title="Coverpop: Most Interesting Photos of the Week by krazydad / jbum, on Flickr" href="http://www.flickr.com/photos/krazydad/2756540506/" title="Coverpop: Most Interesting Photos of the Week by krazydad / jbum, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3123/2756540506_94cf6401ff.jpg" alt="Coverpop: Most Interesting Photos of the Week" width="500" height="380" /> </a></p> <p>I have a &quot;cron job&quot; which runs on one of my computers at home, which updates this mosaic every week, so the photos in it are always fresh. Incidentally, I prefer to call this process a &quot;cron joy.&quot; Oh, nerd humor&#8230;</p> <p><b>2. What are the best tricks or tips you&#8217;ve learned working with the Flickr API?</b></p> <p><i>Jim:</i> I think every Flickr hackr should have access to a powerful high level<br /> graphics library. My library of choice is ImageMagick combined with the Perl programming language (it also works nicely with Ruby), but the GD library, which works with various languages, and PIL, for Python, are also good.</p> <p>I not only use ImageMagick for building mosaics and graphs, but also for &quot;under the hood&quot; kinds of things, like measuring the average colors of photos for the Colr Pickr (see below).</p> <p><b>3. As a Flickr developer what would you like to see Flickr do more of and why?</b></p> <p><i>Jim:</i> One of the very first Flickr hacks I made was the Colr Pickr</p> <p><a href="http://www.krazydad.com/colrpickr/">www.krazydad.com/colrpickr/</a></p> <p>&#8230;which allows photos to be selected by color. Since that appeared, I&#8217;ve worked on, and seen some fancier variations on the concept, that allow larger quantities of Flickr photos to be selected using multiple colors. But all these systems, require that thousands or even millions of thumbnails be downloaded and analyzed for color. This is because Flickr does not supply &quot;average color&quot; information in its APIs, and cannot provide the color search functionality that this data would enable.</p> <p><a title="flickr Colr Pickr by earthhopper, on Flickr" href="http://www.flickr.com/photos/earthhopper/41684259/" title="flickr Colr Pickr by earthhopper, on Flickr"><img loading="lazy" decoding="async" src="http://farm1.static.flickr.com/25/41684259_0a718f1eb6_o.jpg" alt="flickr Colr Pickr" width="383" height="377" /> </a></p> <p>I would like to see Flickr provide, via it&#8217;s APIs, the three most common colors in each photo (using cluster analysis), and provide a way to search for photos which match one, two, or three colors. These parameters, similar to geocode searches, would need to be combined with some other search parameters, such as tags, to narrow<br /> the field down.</p> <p>A feature like this would be a godsend to designers. I&#8217;ve got sample code for the color analysis, if anyone&#8217;s interested&#8230; :)</p> <p><b>4. What excites you about Flick and hacking? What do you think you&#8217;ll build next or would like someone else to build so you don&#8217;t have to?</b></p> <p><i>Jim:</i> One thing that excites me is the ability to access large quantities of photos that contain valuable metadata, such as the time the photo was taken, or the geocoded location. I used the &#8216;date taken&#8217; data to construct this very cool graph of sunsets:</p> <p><a title="A year of sunsets by krazydad / jbum, on Flickr" href="http://www.flickr.com/photos/krazydad/292081922/" title="A year of sunsets by krazydad / jbum, on Flickr"><img loading="lazy" decoding="async" src="http://farm1.static.flickr.com/107/292081922_a31a41cd6b.jpg" alt="A year of sunsets" width="500" height="250" /> </a></p> <p>While most digital cameras store the time within photos, these days, not enough of them automatically store the location. We have to rely on photographers adding the geocoded information manually, and sadly, not enough of them are geeky enough to do it. I&#8217;m looking forward to the day, a few years from now, when most of the new photos on Flickr will also contain geocoded information, as this will enable me to make apps which enable a kind of instant photo-journalism of heavily photographed events, such as rallies and parades. We&#8217;re seeing the beginnings of these kind of apps now, but we&#8217;re barely scratching the surface.</p> <p><b>5. Besides your own, what Flickr projects and hacks do you use on a regular basis? Who should we interview next?</b></p> <p><a title="mc-50 map of FlickrLand: flickr's social network by GustavoG, on Flickr" href="http://www.flickr.com/photos/gustavog/4499404/" title="mc-50 map of FlickrLand: flickr's social network by GustavoG, on Flickr"><img loading="lazy" decoding="async" src="http://farm1.static.flickr.com/3/4499404_e2fb14178a.jpg" alt="mc-50 map of FlickrLand: flickr's social network" width="500" height="273" /> </a></p> <p><i>Jim:</i> <a href="http://flickr.com/photos/gustavog/">GustavoG</a> has made some amazing graphs which exploit and illustrate the Flickr social network.</p> <p><i>Dan:</i> Thank you, Jim. Next up for our thrilling installment of 5 Questions, <a href="http://flickr.com/photos/gustavog/">GustavoG</a> .</p> <p>Images from <a href="http://www.flickr.com/photos/krazydad/">krazydad / jbum</a> , <a href="http://www.flickr.com/photos/earthhopper/">earthhopper</a> and <a href="http://flickr.com/photos/gustavog/"> GustavoG</a>.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/5questions/" rel="tag">5questions</a>, <a href="https://code.flickr.net/tag/api/" rel="tag">api</a>, <a href="https://code.flickr.net/tag/interview/" rel="tag">interview</a>, <a href="https://code.flickr.net/tag/people/" rel="tag">people</a>, <a href="https://code.flickr.net/tag/software/" rel="tag">software</a>, <a href="https://code.flickr.net/tag/tools/" rel="tag">tools</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-194 --> <article id="post-188" class="post-188 post type-post status-publish format-standard hentry category-uncategorized tag-kittentuesday"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/14/kitten-tuesday-4/" rel="bookmark">Kitten Tuesday</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/14/kitten-tuesday-4/" title="4:41 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-14T16:41:41-07:00">October 14, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>Yay it&#8217;s Tuesday and that can mean only one thing!</p> <p>I popped this one into the Kitten <a href="http://code.flickr.com/blog/2008/09/26/flickr-engineers-do-it-offline/">Offline Queue</a> three weeks ago and it&#8217;s finally made it. With a little tuning I&#8217;m told we could easily scale to Kitten November.</p> <p><a title="You need to clone out this shadow here by Daveblog, on Flickr" href="http://www.flickr.com/photos/daveblog/2050611763/" title="You need to clone out this shadow here by Daveblog, on Flickr"><img loading="lazy" decoding="async" src="http://farm3.static.flickr.com/2026/2050611763_649ff6bb8c.jpg" alt="You need to clone out this shadow here" width="500" height="400" /> </a></p> <p>Photo by <a href="http://www.flickr.com/photos/daveblog/">Daveblog</a></p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/kittentuesday/" rel="tag">kittentuesday</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-188 --> <article id="post-174" class="post-174 post type-post status-publish format-standard hentry category-uncategorized tag-dataviz tag-ganglia tag-ops"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/13/flickr-digs-ganglia/" rel="bookmark">Flickr Digs Ganglia</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/13/flickr-digs-ganglia/" title="3:31 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-13T15:31:11-07:00">October 13, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>A number of people have asked us: where did the <a href="http://flickr.com/photos/mylesdgrant/2785644860/">pretty graphs</a> from last week&#8217;s <a href="http://code.flickr.com/blog/2008/09/26/flickr-engineers-do-it-offline/">post</a> come from?</p> <p><a href="http://www.flickr.com/photos/mylesdgrant/2785644860/" title="My Day by Myles!, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3248/2785644860_ec639a8868.jpg" width="500" height="386" alt="My Day" /></a></p> <p>The answer: Ganglia.</p> <p>It takes a lot of hardware and software to make a site like Flickr run smoothly. The operations team is responsible for scaling up our monitoring platform to collect all of the metrics we need to make informed decisions about where and when to add new hosts and how urgently, understand how different types of hardware perform with similar real life workloads, determine bottlenecks, and more. Flickr uses Ganglia to collect, aggregate, and visualize those metrics.</p> <p>So, what is Ganglia? Briefly, &quot;Ganglia is a scalable distributed monitoring system for high-performance computing systems such as clusters and grids&quot;* originally developed at the University of California, Berkeley. Ganglia is typically run by administrators of High Performance Clusters, large groups of machines working together to complete tasks. While we have some machines organized into the traditional cluster configuration, for example for log crunching, we simply define a cluster under Ganglia as a group of machines that do similar things but don&#8217;t necessarily interact with one another. For example, all of our web servers in each site are one cluster and all caches another. Our databases are broken up into multiple clusters based on functionality. This way, boxes that should be doing the same kind of work can be easily compared against one another.</p> <p>Once Ganglia is up and running you&#8217;ll see a number of system level statistics reported by each node. You can also easily report custom metrics and have them appear on graphs along with the built in metrics. Before the latest release (the 3.1.x line), this meant some code that calls gmetric and entry in the crontab for scheduling execution of that code. Ganglia 3.1 offers an additional facility for injecting custom metrics that easy to use and offers some additional power and flexibility over the gmetric + cron approach.</p> <p>For more information on how Ganglia works, see the excellent <a href="http://ganglia.wiki.sourceforge.net/ganglia_documents">references</a> on the <a href="http://ganglia.wiki.sourceforge.net/">Ganglia Wiki</a> . The community is active and very helpful.</p> <p>If you&#8217;re just getting started with Ganglia, here are some pointers to save you headaches later:</p> <ul> <li>Don&#8217;t use the default multicast address 239.2.11.71 for any clusters. You will start gmond without a config file and it will join that first cluster you defined and you will not be happy that your summary graphs are messy.</li> <li>Do put your RRDs on a ramdisk/tmpfs. Your disk(s) will thank you. Don&#8217;t forget to setup a job to sync those files to some persistent storage periodically &#8211; we do it every 10 minutes.</li> <li>Do consider the frequency of data collection and how long you need to keep the data around (and at what resolution). Do you need to know what the 5 minute load average was on your hosts one year ago today (maybe in relation to other metrics)? Do you need to know how many uploads per second those hosts were doing then (certainly)? While individual metric stores can be resized to keep data around for various amounts of time, typically it&#8217;s easier to find the least common denominator &#8211; the largest amount of time you think you need this information for &#8211; and set that in gmetad.conf. The default gmetad config stores data as: <ul> <li>15 second average for about an hour</li> <li>6 minute average for about a day</li> <li>42 minute average for about a week</li> <li>2 hour 48 minute average for about a month</li> <li>1 day average for about a year</li> </ul> </li> </ul> <p>Once you&#8217;re up and running with Ganglia you&#8217;ll have access to something like the graph from the last post, what we call a stacked graph. Stacked graphs are intended to provide a quick overview of the relative performance of each host in a cluster. The code has been submitted to the Ganglia project for all to use.</p> <p>Check out <a href="http://ganglia.info" rel="nofollow">http://ganglia.info</a> for more information and stay tuned for more posts about how Flickr uses Ganglia.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/dataviz/" rel="tag">dataviz</a>, <a href="https://code.flickr.net/tag/ganglia/" rel="tag">ganglia</a>, <a href="https://code.flickr.net/tag/ops/" rel="tag">ops</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-174 --> <article id="post-178" class="post-178 post type-post status-publish format-standard hentry category-uncategorized tag-internationalization tag-urls"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2008/10/08/whats-in-a-resource/" rel="bookmark">What&#8217;s in a Resource?</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2008/10/08/whats-in-a-resource/" title="6:53 pm" rel="bookmark"><time class="entry-date" datetime="2008-10-08T18:53:05-07:00">October 8, 2008</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>&#8220;Flickr is incredibly lucky, because the core of what we do is focused around images.&#8221;</p> <p>If you&#8217;ve ever heard me talk about Internationalizing Flickr, you&#8217;ve probably heard me say those words. And it&#8217;s true &#8211; more than almost any other website, we deal primarily with content which is language-agnostic (and, to a great extent, culturally agnostic).</p> <p>No matter where we live or what language we speak, our reactions to, say, <a href="http://flickr.com/search/?q=fluffy+kittens&#038;s=int">fluffy kittens</a> have a remarkably similar range (being, approximately, &#8220;aww&#8221;, &#8220;ew&#8221; or &#8220;achoo!&#8221;&#8230;)</p> <p>When we first began to define what Flickr&#8217;s international incarnation would look like, our primary concern was preserving this global, cross-cultural feeling &#8211; a sense that our members&#8217; photos and our visitors come from all over the world, but that the images on Flickr can &#8220;speak&#8221; to anyone.</p> <p>It&#8217;s for that reason that Flickr isn&#8217;t divided into national silos &#8211; there&#8217;s no Flickr France, Flickr Brazil or Flickr USA. Much like <a href="http://www.imdb.com/title/tt0091203/">Highlander</a>, <a href="http://flickr.com/search/?q=%22there+can+be+only+one%22&#038;m=text">there can be only one</a> Flickr, and it happens to be accessible in a multi-lingual interface.</p> <p>All well and good, so far.</p> <p>But the biggest issue I wrestled with (and occasionally still do) was what to do with the site&#8217;s URLs. The structure we planned for the site required us to take a definite position on a philosophical issue &#8211; what, in actual fact, constitutes the &#8220;Resource&#8221; defined by the Uniform Resource Locator?</p> <p>There are two possible schools of thought on this &#8211; one which would argue that the photo page <a href="http://www.flickr.com/photos/hitherto/257018778/">http://www.flickr.com/photos/hitherto/257018778/</a> with a French interface is materially different to the same page when presented with an English interface. The French page, we might argue, should be named <a href="http://fr.flickr.com/photos/hitherto/257018778/" rel="nofollow">http://fr.flickr.com/photos/hitherto/257018778/</a>, <a href="http://www.flickr.com/fr-FR/photos/hitherto/257018778/" rel="nofollow">http://www.flickr.com/fr-FR/photos/hitherto/257018778/</a> or something similar.</p> <p>On the other hand (and, in fact, the hand we eventually chose), the real &#8220;resource&#8221; here is the photo (and associated metadata) which the page points to &#8211; the interface is immaterial to the <i>content</i> we&#8217;re presenting. The big advantage of this approach, especially in a multi-lingual world, is that everyone gets the experience best suited to them.</p> <p>A Korean friend, for example, can send me a link to a photo and I will see it on Flickr with the English interface familiar to me. She, meanwhile, can happily browse Flickr in Korean.</p> <p>Things perhaps get murkier if we consider other areas of the site &#8211; the FAQs at <a href="http://flickr.com/help/faq/" rel="nofollow">http://flickr.com/help/faq/</a>, for example. Here, all the content is provided by Flickr, and since all of it is in a particular visitor&#8217;s chosen language, the <i>entire</i> resource is different.</p> <p>Even here, though, the principle can be made to apply. If an English-speaking German friend asks where they can get help on Flickr, I don&#8217;t have to know which language they prefer to view the site in; I can just point them to the FAQ page, and they will have access to the resource (&#8220;help with Flickr&#8221;) which they needed.</p> <p>Now, admittedly, working for a large multi-national company puts me in contact with more than my fair share of people who speak multiple languages, so maybe this matters more to me than to most people. But as our society grows more connected and more mobile, I like to think that the incidences of these kinds of cross-cultural exchanges will only grow.</p> <p>The biggest downside to our current URL approach comes when search engines try to index our content. Since we don&#8217;t have language-specific URLs (and search engine crawlers aren&#8217;t in the habit of changing their language settings and retaining the necessary cookies), everything which search engines index on Flickr comes from our English-language interface.</p> <p>As it happens, depending on how smart the search engines are feeling, this isn&#8217;t <i>too</i> much of a problem &#8211; we do try to surface photo titles and descriptions so that the abstracts make sense. Still, the results returned by <a href="http://search.yahoo.com/search?p=site%3Awww.flickr.com+buzios&#038;ei=UTF-8">Yahoo!</a> and <a href="http://www.google.com/search?q=site%3Awww.flickr.com+buzios&#038;btnG=Search">Google</a> for &#8220;Buzios&#8221; (a beach resort peninsula near Rio in Brazil) give some idea of the nature of the problem.</p> <p>Occasionally, when I&#8217;m hit by a case of perfectionism, such things keep me awake at night. And I&#8217;m sure that someone, somewhere is wailing and gnashing their teeth over how &#8220;Flickr are doing URLs wrong&#8221;.</p> <p>All in all, though, I think we made the right decision.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/internationalization/" rel="tag">internationalization</a>, <a href="https://code.flickr.net/tag/urls/" rel="tag">urls</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-178 --> </div><!-- #content --> </section><!-- #primary --> <div id="secondary" class="widget-area" role="complementary"> <aside id="jetpack-search-filters-3" class="widget jetpack-filters widget_search"> <div id="jetpack-search-filters-3-wrapper" class="jetpack-instant-search-wrapper"> <div class="jetpack-search-form"> <form method="get" id="searchform" action="https://code.flickr.net/"> <label for="s" class="assistive-text">Search</label> <input type="text" class="field" name="s" id="s" placeholder="Search" /> <input type="submit" class="submit" name="submit" id="searchsubmit" value="Search" /> <input type="hidden" name="orderby" value="" /><input type="hidden" name="order" value="" /></form> </div> <h4 class="jetpack-search-filters-widget__sub-heading"> Categories </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="uncategorized"> Uncategorized&nbsp;(136) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="geo"> geo&nbsp;(12) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="kittens"> kittens&nbsp;(10) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="change-log"> changelog&nbsp;(7) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="uploadr"> uploadr&nbsp;(6) </a> </li> </ul> <h4 class="jetpack-search-filters-widget__sub-heading"> Tags </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="api"> api&nbsp;(24) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="geo"> geo&nbsp;(13) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="machine-tags"> machine tags&nbsp;(10) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="javascript"> javascript&nbsp;(9) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="kittentuesday"> kittentuesday&nbsp;(8) </a> </li> </ul> <h4 class="jetpack-search-filters-widget__sub-heading"> Year </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2022-01-01 00:00:00" > 2022&nbsp;(2) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2021-01-01 00:00:00" > 2021&nbsp;(1) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2018-01-01 00:00:00" > 2018&nbsp;(1) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2017-01-01 00:00:00" > 2017&nbsp;(2) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2016-01-01 00:00:00" > 2016&nbsp;(5) </a> </li> </ul> </div></aside> <aside id="recent-posts-2" class="widget widget_recent_entries"> <h3 class="widget-title">Recent Posts</h3> <ul> <li> <a href="https://code.flickr.net/2022/02/14/safer-internet-day-and-open-source-codes-of-conduct/">Safer Internet Day and Open Source Codes of Conduct</a> </li> <li> <a href="https://code.flickr.net/2022/01/04/a-pluggable-solution-for-api-observability-on-our-php-system/">A Pluggable Solution for API Observability on our PHP System</a> </li> <li> <a href="https://code.flickr.net/2021/11/22/flickr-engineering-team-vision-guiding-principles/">Flickr Engineering Team Vision &#038; Guiding Principles</a> </li> <li> <a href="https://code.flickr.net/2018/04/20/together/">Together</a> </li> <li> <a href="https://code.flickr.net/2017/03/07/introducing-similarity-search-at-flickr/">Introducing Similarity Search at Flickr</a> </li> </ul> </aside><aside id="archives-2" class="widget widget_archive"><h3 class="widget-title">Archives</h3> <ul> <li><a href='https://code.flickr.net/2022/02/'>February 2022</a></li> <li><a href='https://code.flickr.net/2022/01/'>January 2022</a></li> <li><a href='https://code.flickr.net/2021/11/'>November 2021</a></li> <li><a href='https://code.flickr.net/2018/04/'>April 2018</a></li> <li><a href='https://code.flickr.net/2017/03/'>March 2017</a></li> <li><a href='https://code.flickr.net/2017/01/'>January 2017</a></li> <li><a href='https://code.flickr.net/2016/09/'>September 2016</a></li> <li><a href='https://code.flickr.net/2016/05/'>May 2016</a></li> <li><a href='https://code.flickr.net/2016/04/'>April 2016</a></li> <li><a href='https://code.flickr.net/2016/03/'>March 2016</a></li> <li><a href='https://code.flickr.net/2015/12/'>December 2015</a></li> <li><a href='https://code.flickr.net/2015/11/'>November 2015</a></li> <li><a href='https://code.flickr.net/2015/09/'>September 2015</a></li> <li><a href='https://code.flickr.net/2015/07/'>July 2015</a></li> <li><a href='https://code.flickr.net/2015/06/'>June 2015</a></li> <li><a href='https://code.flickr.net/2015/03/'>March 2015</a></li> <li><a href='https://code.flickr.net/2014/10/'>October 2014</a></li> <li><a href='https://code.flickr.net/2014/08/'>August 2014</a></li> <li><a href='https://code.flickr.net/2014/07/'>July 2014</a></li> <li><a href='https://code.flickr.net/2014/05/'>May 2014</a></li> <li><a href='https://code.flickr.net/2014/04/'>April 2014</a></li> <li><a href='https://code.flickr.net/2014/02/'>February 2014</a></li> <li><a href='https://code.flickr.net/2013/09/'>September 2013</a></li> <li><a href='https://code.flickr.net/2013/06/'>June 2013</a></li> <li><a href='https://code.flickr.net/2013/03/'>March 2013</a></li> <li><a href='https://code.flickr.net/2012/12/'>December 2012</a></li> <li><a href='https://code.flickr.net/2012/10/'>October 2012</a></li> <li><a href='https://code.flickr.net/2012/07/'>July 2012</a></li> <li><a href='https://code.flickr.net/2012/06/'>June 2012</a></li> <li><a href='https://code.flickr.net/2012/05/'>May 2012</a></li> <li><a href='https://code.flickr.net/2012/04/'>April 2012</a></li> <li><a href='https://code.flickr.net/2012/02/'>February 2012</a></li> <li><a href='https://code.flickr.net/2012/01/'>January 2012</a></li> <li><a href='https://code.flickr.net/2011/12/'>December 2011</a></li> <li><a href='https://code.flickr.net/2011/10/'>October 2011</a></li> <li><a href='https://code.flickr.net/2011/09/'>September 2011</a></li> <li><a href='https://code.flickr.net/2011/08/'>August 2011</a></li> <li><a href='https://code.flickr.net/2011/07/'>July 2011</a></li> <li><a href='https://code.flickr.net/2011/06/'>June 2011</a></li> <li><a href='https://code.flickr.net/2011/03/'>March 2011</a></li> <li><a href='https://code.flickr.net/2011/02/'>February 2011</a></li> <li><a href='https://code.flickr.net/2011/01/'>January 2011</a></li> <li><a href='https://code.flickr.net/2010/11/'>November 2010</a></li> <li><a href='https://code.flickr.net/2010/10/'>October 2010</a></li> <li><a href='https://code.flickr.net/2010/09/'>September 2010</a></li> <li><a href='https://code.flickr.net/2010/08/'>August 2010</a></li> <li><a href='https://code.flickr.net/2010/07/'>July 2010</a></li> <li><a href='https://code.flickr.net/2010/05/'>May 2010</a></li> <li><a href='https://code.flickr.net/2010/04/'>April 2010</a></li> <li><a href='https://code.flickr.net/2010/03/'>March 2010</a></li> <li><a href='https://code.flickr.net/2010/02/'>February 2010</a></li> <li><a href='https://code.flickr.net/2010/01/'>January 2010</a></li> <li><a href='https://code.flickr.net/2009/12/'>December 2009</a></li> <li><a href='https://code.flickr.net/2009/11/'>November 2009</a></li> <li><a href='https://code.flickr.net/2009/10/'>October 2009</a></li> <li><a href='https://code.flickr.net/2009/09/'>September 2009</a></li> <li><a href='https://code.flickr.net/2009/07/'>July 2009</a></li> <li><a href='https://code.flickr.net/2009/06/'>June 2009</a></li> <li><a href='https://code.flickr.net/2009/05/'>May 2009</a></li> <li><a href='https://code.flickr.net/2009/04/'>April 2009</a></li> <li><a href='https://code.flickr.net/2009/03/'>March 2009</a></li> <li><a href='https://code.flickr.net/2009/02/'>February 2009</a></li> <li><a href='https://code.flickr.net/2009/01/'>January 2009</a></li> <li><a href='https://code.flickr.net/2008/12/'>December 2008</a></li> <li><a href='https://code.flickr.net/2008/11/'>November 2008</a></li> <li><a href='https://code.flickr.net/2008/10/' aria-current="page">October 2008</a></li> <li><a href='https://code.flickr.net/2008/09/'>September 2008</a></li> <li><a href='https://code.flickr.net/2008/08/'>August 2008</a></li> <li><a href='https://code.flickr.net/2008/07/'>July 2008</a></li> <li><a href='https://code.flickr.net/2008/06/'>June 2008</a></li> <li><a href='https://code.flickr.net/2008/05/'>May 2008</a></li> <li><a href='https://code.flickr.net/2008/04/'>April 2008</a></li> </ul> </aside><aside id="categories-2" class="widget widget_categories"><h3 class="widget-title">Categories</h3> <ul> <li class="cat-item cat-item-11749740"><a href="https://code.flickr.net/category/api-2/">API</a> </li> <li class="cat-item cat-item-564792"><a href="https://code.flickr.net/category/change-log/">changelog</a> </li> <li class="cat-item cat-item-5784"><a href="https://code.flickr.net/category/event/">event</a> </li> <li class="cat-item cat-item-29160"><a href="https://code.flickr.net/category/geo/">geo</a> </li> <li class="cat-item cat-item-139037766"><a href="https://code.flickr.net/category/hadoop/">hadoop</a> </li> <li class="cat-item cat-item-32"><a href="https://code.flickr.net/category/infrastructure/">infrastructure</a> </li> <li class="cat-item cat-item-139037765"><a href="https://code.flickr.net/category/kittens/">kittens</a> </li> <li class="cat-item cat-item-20156"><a href="https://code.flickr.net/category/labs/">labs</a> </li> <li class="cat-item cat-item-171"><a href="https://code.flickr.net/category/meta/">meta</a> </li> <li class="cat-item cat-item-7092"><a href="https://code.flickr.net/category/metrics/">metrics</a> </li> <li class="cat-item cat-item-139037764"><a href="https://code.flickr.net/category/open-source/">open source</a> </li> <li class="cat-item cat-item-1930"><a href="https://code.flickr.net/category/performance/">performance</a> </li> <li class="cat-item cat-item-304"><a href="https://code.flickr.net/category/photos/">photos</a> </li> <li class="cat-item cat-item-2373"><a href="https://code.flickr.net/category/search/">search</a> </li> <li class="cat-item cat-item-1"><a href="https://code.flickr.net/category/uncategorized/">Uncategorized</a> </li> <li class="cat-item cat-item-249276"><a href="https://code.flickr.net/category/uploadr/">uploadr</a> </li> <li class="cat-item cat-item-412"><a href="https://code.flickr.net/category/video/">video</a> </li> <li class="cat-item cat-item-830560"><a href="https://code.flickr.net/category/xulrunner/">xulrunner</a> </li> </ul> </aside><aside id="meta-2" class="widget widget_meta"><h3 class="widget-title">Meta</h3> <ul> <li><a href="https://code.flickr.net/wp-login.php">Log in</a></li> <li><a href="https://code.flickr.net/feed/">Entries feed</a></li> <li><a href="https://code.flickr.net/comments/feed/">Comments feed</a></li> <li><a href="https://wordpress.org/">WordPress.org</a></li> </ul> </aside> </div><!-- #secondary .widget-area --> </div><!-- #main --> <footer id="colophon" role="contentinfo"> <div id="site-generator"> &copy; 2025 Flickr, Inc. All rights reserved. | Powered by <a href="https://wpvip.com/?utm_source=vip_powered_wpcom&#038;utm_medium=web&#038;utm_campaign=VIP%20Footer%20Credit&#038;utm_term=code.flickr.net" rel="generator nofollow" class="powered-by-wpcom">WordPress VIP</a> </div> </footer><!-- #colophon --> </div><!-- #page --> <div class="jetpack-instant-search__widget-area" style="display: none"> <div id="jetpack-search-filters-2" class="widget jetpack-filters widget_search"> <div id="jetpack-search-filters-2-wrapper" class="jetpack-instant-search-wrapper"> </div></div> </div> <script type="text/javascript" src="https://code.flickr.net/wp-includes/js/dist/hooks.min.js?m=1739294330g" ></script><script type="text/javascript" src="https://code.flickr.net/wp-includes/js/dist/i18n.min.js?ver=5e580eb46a90c2b997e6" id="wp-i18n-js"></script> <script type="text/javascript" id="wp-i18n-js-after"> /* <![CDATA[ */ wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/wp-content/mu-plugins/jetpack-14.2/jetpack_vendor/automattic/jetpack-assets/build/i18n-loader.js?minify=true&amp;ver=becd7d9884bc1b331e45" id="wp-jp-i18n-loader-js"></script> <script type="text/javascript" id="wp-jp-i18n-loader-js-after"> /* <![CDATA[ */ wp.jpI18nLoader.state = {"baseUrl":"https://code.flickr.net/wp-content/languages/","locale":"en_US","domainMap":{"jetpack-admin-ui":"plugins/jetpack","jetpack-assets":"plugins/jetpack","jetpack-backup-pkg":"plugins/jetpack","jetpack-blaze":"plugins/jetpack","jetpack-boost-core":"plugins/jetpack","jetpack-boost-speed-score":"plugins/jetpack","jetpack-classic-theme-helper":"plugins/jetpack","jetpack-compat":"plugins/jetpack","jetpack-config":"plugins/jetpack","jetpack-connection":"plugins/jetpack","jetpack-explat":"plugins/jetpack","jetpack-forms":"plugins/jetpack","jetpack-image-cdn":"plugins/jetpack","jetpack-import":"plugins/jetpack","jetpack-ip":"plugins/jetpack","jetpack-jitm":"plugins/jetpack","jetpack-licensing":"plugins/jetpack","jetpack-masterbar":"plugins/jetpack","jetpack-my-jetpack":"plugins/jetpack","jetpack-password-checker":"plugins/jetpack","jetpack-plugins-installer":"plugins/jetpack","jetpack-post-list":"plugins/jetpack","jetpack-protect-models":"plugins/jetpack","jetpack-protect-status":"plugins/jetpack","jetpack-publicize-pkg":"plugins/jetpack","jetpack-search-pkg":"plugins/jetpack","jetpack-stats":"plugins/jetpack","jetpack-stats-admin":"plugins/jetpack","jetpack-sync":"plugins/jetpack","jetpack-videopress-pkg":"plugins/jetpack","jetpack-waf":"plugins/jetpack","jetpack-wordads":"plugins/jetpack","woocommerce-analytics":"plugins/jetpack"},"domainPaths":{"jetpack-admin-ui":"jetpack_vendor/automattic/jetpack-admin-ui/","jetpack-assets":"jetpack_vendor/automattic/jetpack-assets/","jetpack-backup-pkg":"jetpack_vendor/automattic/jetpack-backup/","jetpack-blaze":"jetpack_vendor/automattic/jetpack-blaze/","jetpack-boost-core":"jetpack_vendor/automattic/jetpack-boost-core/","jetpack-boost-speed-score":"jetpack_vendor/automattic/jetpack-boost-speed-score/","jetpack-classic-theme-helper":"jetpack_vendor/automattic/jetpack-classic-theme-helper/","jetpack-compat":"jetpack_vendor/automattic/jetpack-compat/","jetpack-config":"jetpack_vendor/automattic/jetpack-config/","jetpack-connection":"jetpack_vendor/automattic/jetpack-connection/","jetpack-explat":"jetpack_vendor/automattic/jetpack-explat/","jetpack-forms":"jetpack_vendor/automattic/jetpack-forms/","jetpack-image-cdn":"jetpack_vendor/automattic/jetpack-image-cdn/","jetpack-import":"jetpack_vendor/automattic/jetpack-import/","jetpack-ip":"jetpack_vendor/automattic/jetpack-ip/","jetpack-jitm":"jetpack_vendor/automattic/jetpack-jitm/","jetpack-licensing":"jetpack_vendor/automattic/jetpack-licensing/","jetpack-masterbar":"jetpack_vendor/automattic/jetpack-masterbar/","jetpack-my-jetpack":"jetpack_vendor/automattic/jetpack-my-jetpack/","jetpack-password-checker":"jetpack_vendor/automattic/jetpack-password-checker/","jetpack-plugins-installer":"jetpack_vendor/automattic/jetpack-plugins-installer/","jetpack-post-list":"jetpack_vendor/automattic/jetpack-post-list/","jetpack-protect-models":"jetpack_vendor/automattic/jetpack-protect-models/","jetpack-protect-status":"jetpack_vendor/automattic/jetpack-protect-status/","jetpack-publicize-pkg":"jetpack_vendor/automattic/jetpack-publicize/","jetpack-search-pkg":"jetpack_vendor/automattic/jetpack-search/","jetpack-stats":"jetpack_vendor/automattic/jetpack-stats/","jetpack-stats-admin":"jetpack_vendor/automattic/jetpack-stats-admin/","jetpack-sync":"jetpack_vendor/automattic/jetpack-sync/","jetpack-videopress-pkg":"jetpack_vendor/automattic/jetpack-videopress/","jetpack-waf":"jetpack_vendor/automattic/jetpack-waf/","jetpack-wordads":"jetpack_vendor/automattic/jetpack-wordads/","woocommerce-analytics":"jetpack_vendor/automattic/woocommerce-analytics/"}}; /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/_static/??/wp-includes/js/dist/vendor/wp-polyfill.min.js,/wp-includes/js/dist/url.min.js?m=1739294330j" ></script><script type="text/javascript" id="jetpack-instant-search-js-before"> /* <![CDATA[ */ var JetpackInstantSearchOptions=JSON.parse(decodeURIComponent("%7B%22overlayOptions%22%3A%7B%22colorTheme%22%3A%22light%22%2C%22enableInfScroll%22%3Atrue%2C%22enableFilteringOpensOverlay%22%3Atrue%2C%22enablePostDate%22%3Atrue%2C%22enableSort%22%3Atrue%2C%22highlightColor%22%3A%22%23FFC%22%2C%22overlayTrigger%22%3A%22submit%22%2C%22resultFormat%22%3A%22expanded%22%2C%22showPoweredBy%22%3Atrue%2C%22defaultSort%22%3A%22relevance%22%2C%22excludedPostTypes%22%3A%5B%5D%7D%2C%22homeUrl%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%22%2C%22locale%22%3A%22en-US%22%2C%22postsPerPage%22%3A10%2C%22siteId%22%3A185426273%2C%22postTypes%22%3A%7B%22post%22%3A%7B%22singular_name%22%3A%22Post%22%2C%22name%22%3A%22Posts%22%7D%2C%22page%22%3A%7B%22singular_name%22%3A%22Page%22%2C%22name%22%3A%22Pages%22%7D%2C%22attachment%22%3A%7B%22singular_name%22%3A%22Media%22%2C%22name%22%3A%22Media%22%7D%7D%2C%22webpackPublicPath%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%5C%2Fwp-content%5C%2Fmu-plugins%5C%2Fjetpack-14.2%5C%2Fjetpack_vendor%5C%2Fautomattic%5C%2Fjetpack-search%5C%2Fbuild%5C%2Finstant-search%5C%2F%22%2C%22isPhotonEnabled%22%3Afalse%2C%22isFreePlan%22%3Afalse%2C%22apiRoot%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%5C%2Fwp-json%5C%2F%22%2C%22apiNonce%22%3A%226427edfc35%22%2C%22isPrivateSite%22%3Afalse%2C%22isWpcom%22%3Afalse%2C%22hasOverlayWidgets%22%3Atrue%2C%22widgets%22%3A%5B%7B%22filters%22%3A%5B%7B%22name%22%3A%22Bylines%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22byline%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_0%22%7D%2C%7B%22name%22%3A%22Categories%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22category%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_1%22%7D%2C%7B%22name%22%3A%22Tags%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22post_tag%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_2%22%7D%2C%7B%22name%22%3A%22Year%22%2C%22type%22%3A%22date_histogram%22%2C%22count%22%3A5%2C%22field%22%3A%22post_date%22%2C%22interval%22%3A%22year%22%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22date_histogram_3%22%7D%5D%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%7D%5D%2C%22widgetsOutsideOverlay%22%3A%5B%7B%22filters%22%3A%5B%7B%22name%22%3A%22Bylines%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22byline%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_4%22%7D%2C%7B%22name%22%3A%22Categories%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22category%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_5%22%7D%2C%7B%22name%22%3A%22Tags%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22post_tag%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_6%22%7D%2C%7B%22name%22%3A%22Year%22%2C%22type%22%3A%22date_histogram%22%2C%22count%22%3A5%2C%22field%22%3A%22post_date%22%2C%22interval%22%3A%22year%22%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22date_histogram_7%22%7D%5D%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%7D%5D%2C%22hasNonSearchWidgets%22%3Afalse%2C%22preventTrackingCookiesReset%22%3Afalse%7D")); /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/wp-content/mu-plugins/jetpack-14.2/jetpack_vendor/automattic/jetpack-search/build/instant-search/jp-search.js?minify=false&amp;ver=da5ecd9f722e7fcb409e" id="jetpack-instant-search-js"></script> <script type="text/javascript" src="//stats.wp.com/w.js?ver=202508" id="jp-tracks-js"></script> <script type="text/javascript" src="https://stats.wp.com/e-202508.js" id="jetpack-stats-js" data-wp-strategy="defer"></script> <script type="text/javascript" id="jetpack-stats-js-after"> /* <![CDATA[ */ _stq = window._stq || []; _stq.push([ "view", JSON.parse("{\"v\":\"ext\",\"blog\":\"185426273\",\"post\":\"0\",\"tz\":\"-8\",\"srv\":\"code.flickr.net\",\"hp\":\"vip\",\"j\":\"1:14.2.1\"}") ]); _stq.push([ "clickTrackerInit", "185426273", "0" ]); /* ]]> */ </script> <script async src="https://embedr.flickr.com/assets/client-code.js" charset="utf-8"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10