rowid,title,contents,year,author,author_slug,published,url,topic 105,Contract Killer,"When times get tough, it can often feel like there are no good people left in the world, only people who haven’t yet turned bad. These bad people will go back on their word, welch on a deal, put themselves first. You owe it to yourself to stay on top. You owe it to yourself to ensure that no matter how bad things get, you’ll come away clean. You owe it yourself and your business not to be the guy lying bleeding in an alley with a slug in your gut. But you’re a professional, right? Nothing bad is going to happen to you. You’re a good guy. You do good work for good people. Think again chump. Maybe you’re a gun for hire, a one man army with your back to the wall and nothing standing between you and the line at a soup kitchen but your wits. Maybe you work for the agency, or like me you run one of your own. Either way, when times get tough and people get nasty, you’ll need more than a killer smile to save you. You’ll need a killer contract too. It was exactly ten years ago today that I first opened my doors for business. In that time I’ve thumbed through enough contracts to fill a filing cabinet. I’ve signed more contracts than I can remember, many so complicated that I should have hired a lawyer (or detective) to make sense of their complicated jargon and solve their cross-reference puzzles. These documents had not been written to be understood on first reading but to spin me around enough times so as to give the other player the upper-hand. If signing a contract I didn’t fully understand made me a stupid son-of-a-bitch, not asking my customers to sign one just makes me plain dumb. I’ve not always been so careful about asking my customers to sign contracts with me as I am now. Somehow in the past I felt that insisting on a contract went against the friendly, trusting relationship that I like to build with my customers. Most of the time the game went my way. On rare the occasions when a fight broke out, I ended up bruised and bloodied. I learned that asking my customers to sign a contract matters to both sides, but what also matters to me is that these contracts should be more meaningful, understandable and less complicated than any of those that I have ever autographed. Writing a killer contract If you are writing a contract between you and your customers it doesn’t have to conform to the seemingly standard format of jargon and complicated legalese. You can be creative. A killer contract will clarify what is expected of both sides and it can also help you to communicate your approach to doing business. It will back-up your brand values and help you to build a great relationship between you and your customers. In other words, a creative contract can be a killer contract. Your killer contract should cover: A simple overview of who is hiring who, what they are being hired to do, when and for how much What both parties agree to do and what their respective responsibilities are The specifics of the deal and what is or isn’t included in the scope What happens when people change their minds (as they almost always do) A simple overview of liabilities and other legal matters You might even include a few jokes To help you along, I will illustrate those bullet points by pointing both barrels at the contract that I wrote and have been using at Stiffs & Nonsense for the past year. My contract has been worth its weight in lead and you are welcome to take all or any part of it to use for yourself. It’s packing a creative-commons attribution share-a-like license. That means you are free to re-distribute it, translate it and otherwise re-use it in ways I never considered. In return I only ask you mention my name and link back to this article. As I am only an amateur detective, you should have it examined thoroughly by your own, trusted legal people if you use it. NB: The specific details of this killer contract work for me and my customers. That doesn’t mean that they will work for you and yours. The ways that I handle design revisions, testing, copyright ownership and other specifics are not the main focus of this article. That you handle each of them carefully when you write your own killer contract is. Kiss Me, Deadly Setting a tone and laying foundations for agreement The first few paragraphs of a killer contract are the most important. Just like a well thought-out web page, these first few words should be simple, concise and include the key points in your contract. As this is the part of the contract that people absorb most easily, it is important that you make it count. Start by setting the overall tone and explaining how your killer contract is structured and why it is different. We will always do our best to fulfill your needs and meet your goals, but sometimes it is best to have a few simple things written down so that we both know what is what, who should do what and what happens if stuff goes wrong. In this contract you won’t find complicated legal terms or large passages of unreadable text. We have no desire to trick you into signing something that you might later regret. We do want what’s best for the safety of both parties, now and in the future. In short You ([customer name]) are hiring us ([company name]) located at [address] to [design and develop a web site] for the estimated total price of [total] as outlined in our previous correspondence. Of course it’s a little more complicated, but we’ll get to that. The Big Kill What both parties agree to do Have you ever done work on a project in good faith for a junior member of a customer’s team, only to find out later that their spending hadn’t been authorized? To make damn sure that does not happen to you, you should ask your customer to confirm that not only are they authorized to enter into your contract but that they will fulfill all of their obligations to help you meet yours. This will help you to avoid any gunfire if, as deadline day approaches, you have fulfilled your side of the bargain but your customer has not come up with the goods. As our customer, you have the power and ability to enter into this contract on behalf of your company or organization. You agree to provide us with everything that we need to complete the project including text, images and other information as and when we need it, and in the format that we ask for. You agree to review our work, provide feedback and sign-off approval in a timely manner too. Deadlines work two ways and you will also be bound by any dates that we set together. You also agree to stick to the payment schedule set out at the end of this contract. We have the experience and ability to perform the services you need from us and we will carry them out in a professional and timely manner. Along the way we will endeavor to meet all the deadlines set but we can’t be responsible for a missed launch date or a deadline if you have been late in supplying materials or have not approved or signed off our work on-time at any stage. On top of this we will also maintain the confidentiality of any information that you give us. My Gun Is Quick Getting down to the nitty gritty What appear at first to be a straight-forward projects can sometimes turn long and complicated and unless you play it straight from the beginning your relationship with your customer can suffer under the strain. Customers do, and should have the opportunity to, change their minds and give you new assignments. After-all, projects should be flexible and few customers know from the get-go exactly what they want to see. If you handle this well from the beginning you will help to keep yourself and your customers from becoming frustrated. You will also help yourself to dodge bullets in the event of a fire-fight. We will create designs for the look-and-feel, layout and functionality of your web site. This contract includes one main design plus the opportunity for you to make up to two rounds of revisions. If you’re not happy with the designs at this stage, you will pay us in full for all of the work that we have produced until that point and you may either cancel this contract or continue to commission us to make further design revisions at the daily rate set out in our original estimate. We know from plenty of experience that fixed-price contracts are rarely beneficial to you, as they often limit you to your first idea about how something should look, or how it might work. We don’t want to limit either your options or your opportunities to change your mind. The estimate/quotation prices at the beginning of this document are based on the number of days that we estimate we’ll need to accomplish everything that you have told us you want to achieve. If you do want to change your mind, add extra pages or templates or even add new functionality, that won’t be a problem. You will be charged the daily rate set out in the estimate we gave you. Along the way we might ask you to put requests in writing so we can keep track of changes. As I like to push my luck when it comes to CSS, it never hurts to head off the potential issue of progressive enrichment right from the start. You should do this too. But don’t forget that when it comes to technical matters your customers may have different expectations or understanding, so be clear about what you will and won’t do. If the project includes XHTML or HTML markup and CSS templates, we will develop these using valid XHTML 1.0 Strict markup and CSS2.1 + 3 for styling. We will test all our markup and CSS in current versions of all major browsers including those made by Apple, Microsoft, Mozilla and Opera. We will also test to ensure that pages will display visually in a ‘similar’, albeit not necessarily an identical way, in Microsoft Internet Explorer 6 for Windows as this browser is now past it’s sell-by date. We will not test these templates in old or abandoned browsers, for example Microsoft Internet Explorer 5 or 5.5 for Windows or Mac, previous versions of Apple’s Safari, Mozilla Firefox or Opera unless otherwise specified. If you need to show the same or similar visual design to visitors using these older browsers, we will charge you at the daily rate set out in our original estimate for any necessary additional code and its testing. The Twisted Thing It is not unheard of for customers to pass off stolen goods as their own. If this happens, make sure that you are not the one left holding the baby. You should also make it clear who owns the work that you make as customers often believe that because they pay for your time, that they own everything that you produce. Copyrights You guarantee to us that any elements of text, graphics, photos, designs, trademarks, or other artwork that you provide us for inclusion in the web site are either owned by your good selfs, or that you have permission to use them. When we receive your final payment, copyright is automatically assigned as follows: You own the graphics and other visual elements that we create for you for this project. We will give you a copy of all files and you should store them really safely as we are not required to keep them or provide any native source files that we used in making them. You also own text content, photographs and other data you provided, unless someone else owns them. We own the XHTML markup, CSS and other code and we license it to you for use on only this project. Vengeance Is Mine! The fine print Unless your work is pro-bono, you should make sure that your customers keep you in shoe leather. It is important that your customers know from the outset that they must pay you on time if they want to stay on good terms. We are sure you understand how important it is as a small business that you pay the invoices that we send you promptly. As we’re also sure you’ll want to stay friends, you agree to stick tight to the following payment schedule. [Payment schedule] No killer contract would be complete without you making sure that you are watching your own back. Before you ask your customers to sign, make it clear-cut what your obligations are and what will happen if any part of your killer contract finds itself laying face down in the dirt. We can’t guarantee that the functions contained in any web page templates or in a completed web site will always be error-free and so we can’t be liable to you or any third party for damages, including lost profits, lost savings or other incidental, consequential or special damages arising out of the operation of or inability to operate this web site and any other web pages, even if you have advised us of the possibilities of such damages. Just like a parking ticket, you cannot transfer this contract to anyone else without our permission. This contract stays in place and need not be renewed. If any provision of this agreement shall be unlawful, void, or for any reason unenforceable, then that provision shall be deemed severable from this agreement and shall not affect the validity and enforceability of any remaining provisions. Phew. Although the language is simple, the intentions are serious and this contract is a legal document under exclusive jurisdiction of [English] courts. Oh and don’t forget those men with big dogs. Survival… Zero! Take it from me, packing a killer contract will help to keep you safe when times get tough, but you must still keep your wits about you and stay on the right side of the law. Don’t be a turkey this Christmas. Be a contract killer. Update, May 2010: For a follow-on to this article see Contract Killer: The Next Hit",2008,Andy Clarke,andyclarke,2008-12-23T00:00:00+00:00,https://24ways.org/2008/contract-killer/,business 109,Geotag Everywhere with Fire Eagle,"A note from the editors: Since this article was written Yahoo! has retired the Fire Eagle service. Location, they say, is everywhere. Everyone has one, all of the time. But on the web, it’s taken until this year to see the emergence of location in the applications we use and build. The possibilities are broad. Increasingly, mobile phones provide SDKs to approximate your location wherever you are, browser extensions such as Loki and Mozilla’s Geode provide browser-level APIs to establish your location from the proximity of wireless networks to your laptop. Yahoo’s Brickhouse group launched Fire Eagle, an ambitious location broker enabling people to take their location from any of these devices or sources, and provide it to a plethora of web services. It enables you to take the location information that only your iPhone knows about and use it anywhere on the web. That said, this is still a time of location as an emerging technology. Fire Eagle stores your location on the web (protected by application-specific access controls), but to try and give an idea of how useful and powerful your location can be — regardless of the services you use now — today’s 24ways is going to build a bookmarklet to call up your location on demand, in any web application. Location Support on the Web Over the past year, the number of applications implementing location features has increased dramatically. Plazes and Brightkite are both full featured social networks based around where you are, whilst Pownce rolled in Fire Eagle support to allow geotagging of all the content you post to their microblogging service. Dipity’s beautiful timeline shows for you moving from place to place and Six Apart’s activity stream for Movable Type started exposing your movements. The number of services that hook into Fire Eagle will increase as location awareness spreads through the developer community, but you can use your location on other sites indirectly too. Consider Flickr. Now world renowned for their incredible mapping and places features, geotagging on Flickr started out as a grassroots extension of regular tagging. That same technique can be used to start rolling geotagging in any publishing platform you come across, for any kind of content. Machine-tags (geo:lat= and geo:lon=) and the adr and geo microformats can be used to enhance anything you write with location information. A crash course in avian inflammability Fire Eagle is a location store. A broker between services and devices which provide location and those which consume it. It’s a switchboard that controls which pieces of your location different applications can see and use, and keeps hidden anything you want kept private. A blog widget that displays your current location in public can be restricted to display just your current city, whilst a service that provides you with a list of the nearest ATMs will operate better with a precise street address. Even if your iPhone tells Fire Eagle exactly where you are, consuming applications only see what you want them to see. That’s important for users to realise that they’re in control, but also important for application developers to remember that you cannot rely on having super-accurate information available all the time. You need to build location aware applications which degrade gracefully, because users will provide fuzzier information — either through choice, or through less accurate sources. Application specific permissions are controlled through an OAuth API. Each application has a unique key, used to request a second, user-specific key that permits access to that user’s information. You store that user key and it remains valid until such a time as the user revokes your application’s access. Unlike with passwords, these keys are unique per application, so revoking the access rights of one application doesn’t break all the others. Building your first Fire Eagle app; Geomarklet Fire Eagle’s developer documentation can take you through examples of writing simple applications using server side technologies (PHP, Python). Here, we’re going to write a client-side bookmarklet to make your location available in every site you use. It’s designed to fast-track the experience of having location available everywhere on web, and show you how that can be really handy. Hopefully, this will set you thinking about how location can enhance the new applications you build in 2009. An oddity of bookmarklets Bookmarklets (or ‘favlets’, for those of an MSIE persuasion) are a strange environment to program in. Critically, you have no persistent storage available. As such, using token-auth APIs in a static environment requires you to build you application in a slightly strange way; authing yourself in advance and then hardcoding the keys into your script. Get started Before you do anything else, go to http://fireeagle.com and log in, get set up if you need to and by all means take a look around. Take a look at the mobile updaters section of the application gallery and perhaps pick out an app that will update Fire Eagle from your phone or laptop. Once that’s done, you need to register for an application key in the developer section. Head straight to /developer/create and complete the form. Since you’re building a standalone application, choose ‘Auth for desktop applications’ (rather than web applications), and select that you’ll be ‘accessing location’, not updating. At the end of this process, you’ll have two application keys, a ‘Consumer Key’ and a ‘Consumer Secret’, which look like these: Consumer Key luKrM9U1pMnu Consumer Secret ZZl9YXXoJX5KLiKyVrMZffNEaBnxnd6M These keys combined allow your application to make requests to Fire Eagle. Next up, you need to auth yourself; granting your new application permission to use your location. Because bookmarklets don’t have local storage, you can’t integrate the auth process into the bookmarklet itself — it would have no way of storing the returned key. Instead, I’ve put together a simple web frontend through which you can auth with your application. Head to Auth me, Amadeus!, enter the application keys you just generated and hit ‘Authorize with Fire Eagle’. You’ll be taken to the Fire Eagle website, just as in regular Fire Eagle applications, and after granting access to your app, be redirected back to Amadeus which will provide you your user tokens. These tokens are used in subsequent requests to read your location. And, skip to the end… The process of building the bookmarklet, making requests to Fire Eagle, rendering it to the page and so forth follows, but if you’re the impatient type, you might like to try this out right now. Take your four API keys from above, and drag the following link to your Bookmarks Toolbar; it contains all the code described below. Before you can use it, you need to edit in your own API keys. Open your browser’s bookmark editor and where you find text like ‘YOUR_CONSUMER_KEY_HERE’, swap in the corresponding key you just generated. Get Location Bookmarklet Basics To start on the bookmarklet code, set out a basic JavaScript module-pattern structure: var Geomarklet = function() { return ({ callback: function(json) {}, run: function() {} }); }; Geomarklet.run(); Next we’ll add the keys obtained in the setup step, and also some basic Fire Eagle support objects: var Geomarklet = function() { var Keys = { consumer_key: 'IuKrJUHU1pMnu', consumer_secret: 'ZZl9YXXoJX5KLiKyVEERTfNEaBnxnd6M', user_token: 'xxxxxxxxxxxx', user_secret: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' }; var LocationDetail = { EXACT: 0, POSTAL: 1, NEIGHBORHOOD: 2, CITY: 3, REGION: 4, STATE: 5, COUNTRY: 6 }; var index_offset; return ({ callback: function(json) {}, run: function() {} }); }; Geomarklet.run(); The Location Hierarchy A successful Fire Eagle query returns an object called the ‘location hierarchy’. Depending on the level of detail shared, the index of a particular piece of information in the array will vary. The LocationDetail object maps the array indices of each level in the hierarchy to something comprehensible, whilst the index_offset variable is an adjustment based on the detail of the result returned. The location hierarchy object looks like this, providing a granular breakdown of a location, in human consumable and machine-friendly forms. ""user"": { ""location_hierarchy"": [{ ""level"": 0, ""level_name"": ""exact"", ""name"": ""707 19th St, San Francisco, CA"", ""normal_name"": ""94123"", ""geometry"": { ""type"": ""Point"", ""coordinates"": [ - 0.2347530752, 67.232323] }, ""label"": null, ""best_guess"": true, ""id"": , ""located_at"": ""2008-12-18T00:49:58-08:00"", ""query"": ""q=707%2019th%20Street,%20Sf"" }, { ""level"": 1, ""level_name"": ""postal"", ""name"": ""San Francisco, CA 94114"", ""normal_name"": ""12345"", ""woeid"": , ""place_id"": """", ""geometry"": { ""type"": ""Polygon"", ""coordinates"": [], ""bbox"": [] }, ""label"": null, ""best_guess"": false, ""id"": 59358791, ""located_at"": ""2008-12-18T00:49:58-08:00"" }, { ""level"": 2, ""level_name"": ""neighborhood"", ""name"": ""The Mission, San Francisco, CA"", ""normal_name"": ""The Mission"", ""woeid"": 23512048, ""place_id"": ""Y12JWsKbApmnSQpbQg"", ""geometry"": { ""type"": ""Polygon"", ""coordinates"": [], ""bbox"": [] }, ""label"": null, ""best_guess"": false, ""id"": 59358801, ""located_at"": ""2008-12-18T00:49:58-08:00"" }, } In this case the first object has a level of 0, so the index_offset is also 0. Prerequisites To query Fire Eagle we call in some existing libraries to handle the OAuth layer and the Fire Eagle API call. Your bookmarklet will need to add the following scripts into the page: The SHA1 encryption algorithm The OAuth wrapper An extension for the OAuth wrapper The Fire Eagle wrapper itself When the bookmarklet is first run, we’ll insert these scripts into the document. We’re also inserting a stylesheet to dress up the UI that will be generated. If you want to follow along any of the more mundane parts of the bookmarklet, you can download the full source code. Rendering This bookmarklet can be extended to support any formatting of your location you like, but for sake of example I’m going to build three common formatters that you’ll find useful for common location scenarios: Sites which already ask for your location; and in publishing systems that accept tags or HTML mark-up. All the rendering functions are items in a renderers object, so they can be iterated through easily, making it trivial to add new formatting functions as your find new use cases (just add another function to the object). var renderers = { geotag: function(user) { if(LocationDetail.EXACT !== index_offset) { return false; } else { var coords = user.location_hierarchy[LocationDetail.EXACT].geometry.coordinates; return ""geo:lat="" + coords[0] + "", geo:lon="" + coords[1]; } }, city: function(user) { if(LocationDetail.CITY < index_offset) { return false; } else { return user.location_hierarchy[LocationDetail.CITY - index_offset].name; } } You should always fail gracefully, and in line with catering to users who choose not to share their location precisely, always check that the location has been returned at the level you require. Geotags are expected to be precise, so if an exact location is unavailable, returning false will tell the rendering aspect of the bookmarklet to ignore the function altogether. These first two are quite simple, geotag returns geo:lat=-0.2347530752, geo:lon=67.232323 and city returns San Francisco, CA. This final renderer creates a chunk of HTML using the adr and geo microformats, using all available aspects of the location hierarchy, and can be used to geotag any content you write on your blog or in comments: html: function(user) { var geostring = ''; var adrstring = ''; var adr = []; adr.push('

'); // city if(LocationDetail.CITY >= index_offset) { adr.push( '\n ' + user.location_hierarchy[LocationDetail.CITY-index_offset].normal_name + ',' ); } // county if(LocationDetail.REGION >= index_offset) { adr.push( '\n ' + user.location_hierarchy[LocationDetail.REGION-index_offset].normal_name + ',' ); } // locality if(LocationDetail.STATE >= index_offset) { adr.push( '\n ' + user.location_hierarchy[LocationDetail.STATE-index_offset].normal_name + ',' ); } // country if(LocationDetail.COUNTRY >= index_offset) { adr.push( '\n ' + user.location_hierarchy[LocationDetail.COUNTRY-index_offset].normal_name + '' ); } // postal if(LocationDetail.POSTAL >= index_offset) { adr.push( '\n ' + user.location_hierarchy[LocationDetail.POSTAL-index_offset].normal_name + ',' ); } adr.push('\n

\n'); adrstring = adr.join(''); if(LocationDetail.EXACT === index_offset) { var coords = user.location_hierarchy[LocationDetail.EXACT].geometry.coordinates; geostring = '

' +'\n ' + coords[0] + ';' + '\n ' + coords[1] + '\n

\n'; } return (adrstring + geostring); } Here we check the availability of every level of location and build it into the adr and geo patterns as appropriate. Just as for the geotag function, if there’s no exact location the geo markup won’t be returned. Finally, there’s a rendering method which creates a container for all this data, renders all the applicable location formats and then displays them in the page for a user to copy and paste. You can throw this together with DOM methods and some simple styling, or roll in some components from YUI or JQuery to handle drawing full featured overlays. You can see this simple implementation for rendering in the full source code. Make the call With a framework in place to render Fire Eagle’s location hierarchy, the only thing that remains is to actually request your location. Having already authed through Amadeus earlier, that’s as simple as instantiating the Fire Eagle JavaScript wrapper and making a single function call. It’s a big deal that whilst a lot of new technologies like OAuth add some complexity and require new knowledge to work with, APIs like Fire Eagle are really very simple indeed. return { run: function() { insert_prerequisites(); setTimeout( function() { var fe = new FireEagle( Keys.consumer_key, Keys.consumer_secret, Keys.user_token, Keys.user_secret ); var script = document.createElement('script'); script.type = 'text/javascript'; script.src = fe.getUserUrl( FireEagle.RESPONSE_FORMAT.json, 'Geomarklet.callback' ); document.body.appendChild(script); }, 2000 ); }, callback: function(json) { if(json.rsp && 'fail' == json.rsp.stat) { alert('Error ' + json.rsp.code + "": "" + json.rsp.message); } else { index_offset = json.user.location_hierarchy[0].level; draw_selector(json); } } }; We first insert the prerequisite scripts required for the Fire Eagle request to function, and to prevent trying to instantiate the FireEagle object before it’s been loaded over the wire, the remaining instantiation and request is wrapped inside a setTimeout delay. We then create the request URL, referencing the Geomarklet.callback callback function and then append the script to the document body — allowing a cross-domain request. The callback itself is quite simple. Check for the presence and value of rsp.status to test for errors, and display them as required. If the request is successful set the index_offset — to adjust for the granularity of the location hierarchy — and then pass the object to the renderer. The result? When Geomarklet.run() is called, your location from Fire Eagle is read, and each renderer displayed on the page in an easily copy and pasteable form, ready to be used however you need. Deploy The final step is to convert this code into a long string for use as a bookmarklet. Easiest for Mac users is the JavaScript bundle in TextMate — choose Bundles: JavaScript: Copy as Bookmarklet to Clipboard. Then create a new ‘Get Location’ bookmark in your browser of choice and paste in. Those without TextMate can shrink their code down into a single line by first running their code through the JSLint tool (to ensure the code is free from errors and has all the required semi-colons) and then use a find-and-replace tool to remove line breaks from your code (or even run your code through JSMin to shrink it down). With the bookmarklet created and added to your bookmarks bar, you can now call up your location on any page at all. Get a feel for a web where your location is just another reliable part of the browsing experience. Where next? So, the Geomarklet you’ve been guided through is a pretty simple premise and pretty simple output. But from this base you can start to extend: Add code that will insert each of the location renderings directly into form fields, perhaps, or how about site-specific handlers to add your location tags into the correct form field in Wordpress or Tumblr? Paste in your current location to Google Maps? Or Flickr? Geomarklet gives you a base to start experimenting with location on your own pages and the sites you browse daily. The introduction of consumer accessible geo to the web is an adventure of discovery; not so much discovering new locations, but discovering location itself.",2008,Ben Ward,benward,2008-12-21T00:00:00+00:00,https://24ways.org/2008/geotag-everywhere-with-fire-eagle/,code 100,Moo'y Christmas,"A note from the editors: Moo has changed their API since this article was written. As the web matures, it is less and less just about the virtual world. It is becoming entangled with our world and it is harder to tell what is virtual and what is real. There are several companies who are blurring this line and make the virtual just an extension of the physical. Moo is one such company. Moo offers simple print on demand services. You can print business cards, moo mini cards, stickers, postcards and more. They give you the ability to upload your images, customize them, then have them sent to your door. Many companies allow this sort of digital to physical interaction, but Moo has taken it one step further and has built an API. Printable stocking stuffers The Moo API consists of a simple XML file that is sent to their servers. It describes all the information needed to dynamically assemble and print your object. This is very helpful, not just for when you want to print your own stickers, but when you want to offer them to your customers, friends, organization or community with no hassle. Moo handles the check-out and shipping, all you need to do is what you do best, create! Now using an API sounds complicated, but it is actually very easy. I am going to walk you through the options so you can easily be printing in no time. Before you can begin sending data to the Moo API, you need to register and get an API key. This is important, because it allows Moo to track usage and to credit you. To register, visit http://www.moo.com/api/ and click “Request an API key”. In the following examples, I will use {YOUR API KEY HERE} as a place holder, replace that with your API key and everything will work fine. First thing you need to do is to create an XML file to describe the check-out basket. Open any text-editor and start with some XML basics. Don’t worry, this is pretty simple and Moo gives you a few tools to check your XML for errors before you order. 0.7 {YOUR API KEY HERE} build http://www.example.com/return.html http://www.example.com/fail.html ... Much like HTML’s and , Moo has created and elements all wrapped in a element. The element contains a few pieces of information that is the same across all the API calls. The element describes which version of the API is being used. This is more important for Moo than for you, so just stick with “0.7” for now. The allows Moo to track sales, referrers and credit your account. The element can only take “build” so that is pretty straight forward. The and elements are URLs. These are optional and are the URLs the customer is redirected to if there is an error, or when the check out process is complete. This allows for some basic branding and a custom “thank you” page which is under your control. That’s it for the element, pretty easy so far! Next up is the element. What goes inside here describes what is to be printed. There are two possible elements, we can put or we can put directly inside . They work in a similar ways, but they drop the customer into different parts of the Moo checkout process. If you specify then you send the customer straight to the Moo payment process. If you specify then you send the customer one-step earlier where they are allowed to pick and choose some images, remove the ones they don’t like, adjust the crop, etc. The example here will use but with a little bit of homework you can easily adjust to if you desire. ... sticker http://example.com/images/christmas1.jpg ... Inside the element, we can see there are two basic piece of information. The type of product we want to print, and the images that are to be printed. The element can take one of five options and is required! The possibilities are: minicard, notecard, sticker, postcard or greetingcard. We’ll now look at two of these more closely. Moo Stickers In the Moo sticker books you get 90 small squarish stickers in a small little booklet. The simplest XML you could send would be something like the following payload: ... sticker http://example.com/image1.jpg http://example.com/image2.jpg http://example.com/image3.jpg ... This creates a sticker book with only 3 unique images, but 30 copies of each image. The Sticker books always print 90 stickers in multiples of the images you uploaded. That example only has 3 elements, but you can easily duplicate the XML and send up to 90. The should be the full path to your image and the image needs to be a minimum of 300 pixels by 300 pixels. You can add more XML to describe cropping, but the simplest option is to either, let your customers choose or to pre-crop all your images square so there are no issues. The full XML you would post to the Moo API to print sticker books would look like this: 0.7 {YOUR API KEY HERE} build http://www.example.com/return.html http://www.example.com/fail.html sticker http://example.com/image1.jpg http://example.com/image2.jpg http://example.com/image3.jpg Mini-cards The mini-cards are the small cute business cards in 14×35 dimensions and come in packs of 100. Since the mini-cards are print on demand, this allows you to have 100 unique images on the back of the cards. Just like the stickers example, we need the same XML setup. The element and elements will be the same as before. The part you will focus on is the section. Since you are sending along specific information, we can’t use the option any more. Switch this to which has a child of , which in turn has a and . This might seem like a lot of work, but once you have it set up you won’t need to change it. ... minicard ... ... So now that we have the basic framework, we can talk about the information specific to minicards. Inside the element, you will have one for each card. Much like before, this contains a way to describe the image. Note that this time the element is called , not images plural. Inside the element you have a which points to where the image lives and a . The should just be set to ‘variable’. You can pass crop information here instead, but we’re going to keep it simple for this tutorial. If you are interested in how that works, you should refer to the official API documentation. ... http://example.com/image1.jpg variable ... So far, we have managed to build a pack of 100 Moo mini-cards with the same image on the front. If you wanted 100 different images, you just need to replicate this snippit, 99 more times. That describes the front design, but the flip-side of your mini-cards can contain 6 lines of text, which is customizable in a variety of colors, fonts and styles. The API allows you to create different text on the back of each mini-card, something the web interface doesn’t implement. To describe the text on the mini-card we need to add a element inside the element. If you skip this element, the back of your mini-card will just be blank, but that’s not very festive! Inside the element, we need to describe the type of text we want to format, so we add a element, which in turn contains all the lines of text. Each of Moo’s printed products take different numbers of lines of text, so if you are not planning on making mini-cards, be sure to consult the documentation. For mini-cards, we can have 6 distinct lines, each with their own style and layout. Each line is represented by an element which has several optional children. The tells which line of the 6 to print the text one. The is the text you want to print and it must be shorter than 38 characters. The element is false by default, but if you want your text bolded, then add this and set it to true. The element is also optional. By default it is set to align left. You can also set this to right or center if you desirer. The element takes one of 3 types, modern, traditional or typewriter. The default is modern. Finally, you can set the , yes that’s color with a ‘u’, Moo is a British company, so they get to make the rules. When you start a print on demand company, you can spell it however you want. The element takes a 6 character hex value with a leading #. ... (1-6) String, I must be less than 38 chars! true left modern #ff0000 If you combine all of this into a mini-card request you’d get this example: 0.7 {YOUR API KEY HERE} build http://www.example.com/return.html http://www.example.com/fail.html minicard http://example.com/image1.jpg variable 1 String, I must be less than 38 chars! true left modern #ff0000 Now you know how to construct the XML that describes what to print. Next, you need to know how to send it to Moo to make it happen! Posting to the API So your XML is file ready to go. First thing we need to do is check it to make sure it’s valid. Moo has created a simple validator where you paste in your XML, and it alerts you to problems. When you have a fully valid XML file, you’ll want to send that to the Moo API. There are a few ways to do this, but the simplest is with an HTML form. This is the sample code for an HTML form with a big “Buy My Stickers” button. Once you know that it is working, you can use all your existing HTML knowledge to style it up any way you like.
.... ... "">
This is just a basic
element that submits to the Moo API, http://www.moo.com/api/api.php, when someone clicks the button. There is a hidden input called “xml” which contains the value the XML file we created previously. For those of you who need to “view source” to fully understand what’s happening can see a working version and peek under the hood. Using the API has advantages over uploading the images directly yourself. The images and text that you send via the API can be dynamic. Some companies, like Dopplr, have taken user profiles and dynamic data that changes every minute to generate customer stickers of places that you’ve travelled to or mini-cards with a world map of all the cities you have visited. Every single customer has different travel plans and therefore different sets of stickers and mini-card maps. The API allows for the utmost current information to be printed, on demand, in real-time. Go forth and Moo’ltiply See, making an API call wasn’t that hard was it? You are now 90% of the way to creating anything with the Moo API. With a bit of reading, you can learn that extra 10% and print any Moo product. Be on the lookout in 2009 for the official release of the 1.0 API with improvements and some extras that were not available when this article was written. This article is released under the creative-commons attribution share-a-like license. That means you are free to re-distribute it, mash it up, translate it and otherwise re-using it ways the author never considered, in return he only asks you mention his name. This work by Brian Suda is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.",2008,Brian Suda,briansuda,2008-12-19T00:00:00+00:00,https://24ways.org/2008/mooy-christmas/,code 104,Sitewide Search On A Shoe String,"One of the questions I got a lot when I was building web sites for smaller businesses was if I could create a search engine for their site. Visitors should be able to search only this site and find things without the maintainer having to put “related articles” or “featured content” links on every page by hand. Back when this was all fields this wasn’t easy as you either had to write your own scraping tool, use ht://dig or a paid service from providers like Yahoo, Altavista or later on Google. In the former case you had to swallow the bitter pill of computing and indexing all your content and storing it in a database for quick access and in the latter it hurt your wallet. Times have moved on and nowadays you can have the same functionality for free using Yahoo’s “Build your own search service” – BOSS. The cool thing about BOSS is that it allows for a massive amount of hits a day and you can mash up the returned data in any format you want. Another good feature of it is that it comes with JSON-P as an output format which makes it possible to use it without any server-side component! Starting with a working HTML form In order to add a search to your site, you start with a simple HTML form which you can use without JavaScript. Most search engines will allow you to filter results by domain. In this case we will search “bbc.co.uk”. If you use Yahoo as your standard search, this could be:
The Google equivalent is:
In any case make sure to use the ID term for the search term and site for the site, as this is what we are going to use for the script. To make things easier, also have an ID called customsearch on the form. To use BOSS, you should get your own developer API for BOSS and replace the one in the demo code. There is click tracking on the search results to see how successful your app is, so you should make it your own. Adding the BOSS magic BOSS is a REST API, meaning you can use it in any HTTP request or in a browser by simply adding the right parameters to a URL. Say for example you want to search “bbc.co.uk” for “christmas” all you need to do is open the following URL: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&format=xml&appid=YOUR-APPLICATION-ID Try it out and click it to see the results in XML. We don’t want XML though, which is why we get rid of the format=xml parameter which gives us the same information in JSON: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&appid=YOUR-APPLICATION-ID JSON makes most sense when you can send the output to a function and immediately use it. For this to happen all you need is to add a callback parameter and the JSON will be wrapped in a function call. Say for example we want to call SITESEARCH.found() when the data was retrieved we can do it this way: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&callback=SITESEARCH.found&appid=YOUR-APPLICATION-ID You can use this immediately in a script node if you want to. The following code would display the total amount of search results for the term christmas on bbc.co.uk as an alert: However, for our example, we need to be a bit more clever with this. Enhancing the search form Here’s the script that enhances a search form to show results below it. SITESEARCH = function(){ var config = { IDs:{ searchForm:'customsearch', term:'term', site:'site' }, loading:'Loading results...', noresults:'No results found.', appID:'YOUR-APP-ID', results:20 }; var form; var out; function init(){ if(config.appID === 'YOUR-APP-ID'){ alert('Please get a real application ID!'); } else { form = document.getElementById(config.IDs.searchForm); if(form){ form.onsubmit = function(){ var site = document.getElementById(config.IDs.site).value; var term = document.getElementById(config.IDs.term).value; if(typeof site === 'string' && typeof term === 'string'){ if(typeof out !== 'undefined'){ out.parentNode.removeChild(out); } out = document.createElement('p'); out.appendChild(document.createTextNode(config.loading)); form.appendChild(out); var APIurl = 'http://boss.yahooapis.com/ysearch/web/v1/' + term + '?callback=SITESEARCH.found&sites=' + site + '&count=' + config.results + '&appid=' + config.appID; var s = document.createElement('script'); s.setAttribute('src',APIurl); s.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(s); return false; } }; } } }; function found(o){ var list = document.createElement('ul'); var results = o.ysearchresponse.resultset_web; if(results){ var item,link,description; for(var i=0,j=results.length;i
Where to go from here This is just a very simple example of what you can do with BOSS. You can define languages and regions, retrieve and display images and news and mix the results with other data sources before displaying them. One very cool feature is that by adding a view=keyterms parameter to the URL you can get the keywords of each of the results to drill deeper into the search. An example for this written in PHP is available on the YDN blog. For JavaScript solutions there is a handy wrapper called yboss available to help you go nuts.",2008,Christian Heilmann,chrisheilmann,2008-12-04T00:00:00+00:00,https://24ways.org/2008/sitewide-search-on-a-shoestring/,code 98,Absolute Columns,"CSS layouts have come quite a long way since the dark ages of web publishing, with all sorts of creative applications of floats, negative margins, and even background images employed in order to give us that most basic building block, the column. As the title implies, we are indeed going to be discussing columns today—more to the point, a handy little application of absolute positioning that may be exactly what you’ve been looking for… Care for a nightcap? If you’ve been developing for the web for long enough, you may be familiar with this little children’s fable, passed down from wizened Shaolin monks sitting atop the great Mt. Geocities: “Once upon a time, multiple columns of the same height could be easily created using TABLES.” Now, though we’re all comfortably seated on the standards train (and let’s be honest: even if you like to think you’ve fallen off, if you’ve given up using tables for layout, rest assured your sleeper car is still reserved), this particular—and as page layout goes, quite basic—trick is still a thorn in our CSSides compared to the ease of achieving the same effect using said Tables of Evil™. See, the orange juice masks the flavor… Creative solutions such as Dan Cederholm’s Faux Columns do a good job of making it appear as though adjacent columns maintain equal height as content expands, using a background image to fill the space that the columns cannot. Now, the Holy Grail of CSS columns behaving exactly how they would as table cells—or more to the point, as columns—still eludes us (cough CSS3 Multi-column layout module cough), but sometimes you just need, for example, a secondary column (say, a sidebar) to match the height of a primary column, without involving the creation of images. This is where a little absolute positioning can save you time, while possibly giving your layout a little more flexibility. Shaken, not stirred You’re probably familiar by now with the concept of Making the Absolute, Relative as set forth long ago by Doug Bowman, but let’s quickly review just in case: an element set to position:absolute will position itself relative to its nearest ancestor set to position:relative, rather than the browser window (see Figure 1). Figure 1. However, what you may not know is that we can anchor more than two sides of an absolutely positioned element. Yes, that’s right, all four sides (top, right, bottom, left) can be set, though in this example we’re only going to require the services of three sides (see Figure 2 for the end result). Figure 2. Trust me, this will make you feel better Our requirements are essentially the same as the standard “absolute-relative” trick—a container
set to position:relative, and our sidebar
set to position:absolute — plus another
that will serve as our main content column. We’ll also add a few other common layout elements (wrapper, header, and footer) so our example markup looks more like a real layout and less like a test case:

#header

#left

Lorem ipsum dolor sit amet…

#right

#footer

In this example, our main column (#column-left) is only being given a width to fit within the context of the layout, and is otherwise untouched (though we’re using pixels here, this trick will of course work with fluid layouts as well), and our right keeping our styles nice and minimal: #container { position: relative; } #column-left { width: 480px; } #column-right { position: absolute; top: 10px; right: 10px; bottom: 10px; width: 250px; } The trick is a simple one: the #container
will expand vertically to fit the content within #column-left. By telling our sidebar
(#column-right) to attach itself not only to the top and right edges of #container, but also to the bottom, it too will expand and contract to match the height of the left column (duplicate the “lorem ipsum” paragraph a few times to see it in action). Figure 3. On the rocks “But wait!” I hear you exclaim, “when the right column has more content than the left column, it doesn’t expand! My text runneth over!” Sure enough, that’s exactly what happens, and what’s more, it’s supposed to: Absolutely positioned elements do exactly what you tell them to do, and unfortunately aren’t very good at thinking outside the box (get it? sigh…). However, this needn’t get your spirits down, because there’s an easy way to address the issue: by adding overflow:auto to #column-right, a scrollbar will automatically appear if and when needed: #column-right { position: absolute; top: 10px; right: 10px; bottom: 10px; width: 250px; overflow: auto; } While this may limit the trick’s usefulness to situations where the primary column will almost always have more content than the secondary column—or where the secondary column’s content can scroll with wild abandon—a little prior planning will make it easy to incorporate into your designs. Driving us to drink It just wouldn’t be right to have a friendly, festive holiday tutorial without inviting IE6, though in this particular instance there will be no shaming that old browser into admitting it has a problem, nor an intervention and subsequent 12-step program. That’s right my friends, this tutorial has abstained from IE6-abuse now for 30 days, thanks to the wizard Dean Edwards and his amazingly talented IE7 Javascript library. Simply drop the Conditional Comment and Then you need to initialise Polypage on page load using something along these lines: Next you need to define the areas of your wireframe which are particular to a given state or view. Do this by applying classes beginning with pp_. Polypage will ignore all other classes in the document. The pp_ prefix should be followed by a state name. This can be any text string you like, bearing in mind it will appear in the control bar. Typical page states might include ‘logged_in’, ‘administrator’ or ‘group_owner’. A complete class name would therefore look something like pp_logged_in. Examples If a user is logged in, you might want to specify an option for him or her to sign out. Using Polypage, this could be put in the wireframe as follows: Sign out Polypage will identify the pp_logged_in class on the link and hide it (as the ‘Sign out’ link should only be shown when the page is in the ‘logged in’ view). Polypage will then automatically write a ‘logged in’ toggle to the control bar, enabling you to show or hide the ‘Sign out’ link by toggling the ‘logged in’ view. The same will apply to all content marked with a pp_logged_in class. States can also be negated by adding a not keyword to the class name. For example you might want to provide a log in link for users who are not signed in. Using Polypage, you would insert the not keyword after the pp prefix as follows: Login Again Polypage identifies the pp prefix but this time sees that the ‘Login’ link should not be shown when the ‘logged in’ state is selected. States can also be joined together to add some basic logic to pages. The syntax follows natural language and uses the or and and keywords in addition to the afore-mentioned not. Some examples would be pp_logged_in_and_admin, pp_admin_or_group_owner and pp_logged_in_and_not_admin. Finally, you can set default states for a page by passing an array to the polypage.init() function like this: $.polypage.init(['logged_in', 'admin']); You can see a fully fledged example in this fictional social network group page. The example page defaults to a logged in state. You can see the logged out state by toggling ‘logged in’ off in the Polypage control bar. There are also views specified for a group member, a group admin, a new group and notes. Where can I get hold of it? You can download the current version from GitHub. Polypage was originally developed by Clearleft and New Bamboo, with particular contributions from Andy Kent and Natalie Downe. It has been used in numerous real projects, but it is still an early release so there is bound to be room for improvement. We’re pleased to say that Polypage is now an open source project so any feedback, particularly by way of actual improvements, is extremely welcome.",2008,Richard Rutter,richardrutter,2008-12-11T00:00:00+00:00,https://24ways.org/2008/easier-page-states-for-wireframes/,process 119,Rocking Restrictions,"I love my job. I live my job. For every project I do, I try to make it look special. I’ll be honest: I have a fetish for comments like “I never saw anything like that!” or, “I wish I thought of that!”. I know, I have an ego-problem. (Eleven I’s already) But sometimes, you run out of inspiration. Happens to everybody, and everybody hates it. “I’m the worst designer in the world.” “Everything I designed before this was just pure luck!” No it wasn’t. Countless articles about finding inspiration have already been written. Great, but they’re not the magic potion you’d expect them to be when you need it. Here’s a list of small tips that can have immediate effect when applying them/using them. Main theme: Liberate yourself from the designers’ block by restricting yourself. Do’s Grids If you aren’t already using grids, you’re doing something wrong. Not only are they a great help for aligning your design, they also restrict you to certain widths and heights. (For more information about grids, I suggest you read Mark Boulton’s series on designing grid systems. Oh, he’s also publishing a book I think.) So what’s the link between grids and restrictions? Instead of having the option to style a piece of layout with a width of 1 to 960 pixels, you have to choose from values like 60 pixels, 140, 220, 300, … Start small Having a hard time finding a style for the layout, why don’t you start with one small object? No, not that small object, I meant a piece of a form, or a link, or try styling your headers (h1 – h6). Let’s take a submit button of a form: it’s small, but needs much attention. People will click it. People will hover it. Maybe sometimes it’s disabled? Also: a button needs to look like a button, so typically it requires more styling then a regular link. Once you’ve got the button, move on, following the button’s style. Color palettes There are lots of resources on the web for finding inspiration for color palettes. Some of the most famous are COLOURlovers, wear palettes and Adobe’s Kuler. Browse through them (or create your own from a picture), pick a color palette you like and which works with the subject you’re handling, and stick with it. 4-5 colors, maybe with some tonal variations, but that’s it. Fonts There aren’t many fonts available for the web (Richard Rutter has a great article on this subject), but you’d be surprised how long they go. A simple text-transform: uppercase; or font-style: italic; can change a dull looking font into something entirely fresh. Play around with the fonts you want to use and the variations you’ll be using, and make a list. Pick five combinations of fonts and their variations, and stick with them throughout the layout. Single-task Most of us use multiple monitors. They’re great to increase productivity, but make it harder to focus on a single task. Here’s what you do: try using only your smallest monitor. Maybe it’s the one from your laptop, maybe it’s an old 1024×768 you found in the attic. Having Photoshop (or Fireworks or…) taking over your entire workspace blocks out all the other distractions on your screen, and works quite liberating. Mute everything… …but not entirely. I noticed I was way more focused when I set NetNewsWire to refresh it’s feeds only once every two hours. After two hours, I need a break anyway. Turning off Twitterrific was a mistake, as it’s my window to the world, and it’s the place where the people I like to call colleagues live. You can’t exactly ask them to bring you a cup of coffee when they go to the vending machine, but they do keep you fresh, and it stops you from going human-shy. Instead I changed the settings to not play a notification sound when new Tweets arrive so it doesn’t disturb me when I’m zoning. Don’ts CSS galleries Don’t start browsing all kinds of CSS galleries. Either you’ll feel bad, or you just start using elements in a way you can’t call “inspired” anymore. Instead gather your own collection of inspiration. Example: I use LittleSnapper in which I dump everything I find inspiring. This goes from a smart layout idea, to a failed picture someone posted on Flickr. Everything is inspiring. Panicking Don’t panic. It’s the worst thing you could do. Instead, get away from the computer, and go to bed early. A good night of sleep combined with a hot/cold shower can give you a totally new perspective on a design. Got a deadline by tomorrow? Well, you should’ve started earlier. Got a good excuse to start on this design this late? Tell your client it was either that or a bad design. 120-hour work-week Don’t work all day long, including evenings and early mornings. Write off that first hour, you don’t really think you’ll get anything productive done before 9AM?! I don’t even think you should work on one and the same design all day long. If you’re stuck, try working in blocks of 1 or 2 hours on a certain design. Mixing projects isn’t for everyone, but it might just do the trick for you. Summary Use grids, not only for layout purposes. Pick a specific element to start with. Use a colour palette. Limit the amount of fonts and variations you’ll use. Search for the smallest monitor around, and restrict yourself to that one. Reduce the amount of noise. Don’t start looking on the internet for inspiration. Build your own little inspirarchive. Work in blocks.",2008,Tim Van Damme,timvandamme,2008-12-14T00:00:00+00:00,https://24ways.org/2008/rocking-restrictions/,process 111,Geometric Background Patterns,"When the design is finished and you’re about to start the coding process, you have to prepare your graphics. If you’re working with a pattern background you need to export only the repeating fragment. It can be a bit tricky to isolate a fragment to achieve a seamless pattern background. For geometric patterns there is a method I always follow and that I want to share with you. Take for example a perfect 45° diagonal line pattern. How do you define this pattern fragment so it will be rendered seamlessly? Here is the method I usually follow to avoid a mismatch. First, zoom in so you see enough detail and you can distinguish the pixels. Select the Rectangular Marquee Selection tool and start your selection at the intersection of 2 different colors of a diagonal line. Hold down the Shift key while dragging so you drag a perfect square. Release the mouse when you reach the exact same intesection (as your starting) point at the top right. Copy this fragment (using Copy Merged: Cmd/Ctrl + Shift + C) and paste the fragment in a new layer. Give this layer the name ‘pattern’. Now hold down the Command Key (Control Key on Windows) and click on the ‘pattern’ layer in the Layers Palette to select the fragment. Now go to Edit > Define Pattern, enter a name for your pattern and click OK. Test your pattern in a new document. Create a new document of 600 px by 400px, hit Cmd/Ctrl + A and go to Edit > Fill… and choose your pattern. If the result is OK, you have created a perfect pattern fragment. Below you see this pattern enlarged. The guides show the boundaries of the pattern fragment and the red pixels are the reference points. The red pixels at the top right, bottom right and bottom left should match the red pixel at the top left. This technique should work for every geometric pattern. Some patterns are easier than others, but this, and the Photoshop pattern fill test, has always been my guideline. Other geometric pattern examples Example 1 Not all geometric pattern fragments are squares. Some patterns look easy at first sight, because they look very repetitive, but they can be a bit tricky. Zoomed in pattern fragment with point of reference shown: Example 2 Some patterns have a clear repeating point that can guide you, such as the blue small circle of this pattern as you can see from this zoomed in screenshot: Zoomed in pattern fragment with point of reference shown: Example 3 The different diagonal colors makes a bit more tricky to extract the correct pattern fragment. The orange dot, which is the starting point of the selection is captured a few times inside the fragment selection:",2008,Veerle Pieters,veerlepieters,2008-12-02T00:00:00+00:00,https://24ways.org/2008/geometric-background-patterns/,design