Join our HiFi mailing list to receive the latest news & updates

The HiFi Snippet Library Has Launched

0 Comment(s) | Posted | by Joel Sutherland | |

HiFi Snippets

This morning we're making it official the HiFi Snippet Library has launched.

A great thing about working with HiFi is that you can use the web technologies you know (HTML/CSS/JS) with no restrictions. Many systems say this, we actually mean it. This means that it is extremely easy to build reusable snippets that can save you all kinds of time when building your client sites.

If none of this makes sense to you, hopefully we can answer your questions here.  If you have any others, let us know in the comments.

What is a snippet?

A snippet is a combination of HTML, CSS and JS that you can drop into your sites' templates to quickly implement a feature. Since it is based in just HTML/CSS/JS, it is easy to customize or change them.

Why is this cool?

Snippets let you quickly add functionality to your sites without forcing you to use particular HTML. Design and code the sites the way you want, and then hook up the functionality with snippets.

How much do they cost?

The snippets are completely free.  Most can even be used on non-HiFi sites!

Where are they coming from?

The HiFi snippets are being written both by the HiFi team as they build sites, and by customers using HiFi. If you have a snippet you would like to see, or a snippet you want to contribute to the library, get in contact.

How often will they be released?

We have committed to release at least one snippet a week, but through community contributions, the number may be even higher! Whenever we release a snippet, we will be posting it to the HiFi blog. So be sure to subscribe to the blog to get updated on the newest snippets.

Your snippets are stupid. Why don't you have an XYZ snippet?

We like your attitude. Shoot us a message and we'll make sure it gets added!

HiFi on Forrst

4 Comment(s) | Posted | by Joel Sutherland | |

We've been working away, readying our next major release that will provide better support for agencies and those managing multiple sites.  While this has been in the works, our team discovered Forrst.

forrst

It has turned out to be a great community of people interested in web design/development as a whole, not just some part of it.  We've been putting up some of our ideas and feature screenshots and have been getting some great feedback:

We've also had some good conversations about web technologies that we care about:

If you're on Forrst and want to follow the some of the HiFi team, here are our accounts:

If you're not on Forrst and interested in an invite...we've got a couple, so let us know who you are in the comments.

Overview of Image Formats for the Web

1 Comment(s) | Posted | by Joel Sutherland | |

Graphical elements are a crucial part of every website design. Many people however, do not pay close enough attention to the details of deciding which type of graphical element to use in different circumstances. We've put together a detailed explanation of what an online image is and when it's appropriate to help you decide what type of image to use on your website, depending on the situation. 

The Basics of Online Images

What is an image file?

 An image is a rectangular collection of pixels. On the web, each pixel is made of three colors, Red, Green and Blue. We know what color the pixel is based on the ratio of the different colors. Each color can range from dark (low number) to bright (high number).

How can colors be represented?

There are two different ways that these color values are represented. Some formats are 24-bit, meaning they use 8-bit color depth. This means that each color is stored using 8-bits, or a value from 0 (dark) to 255 (light). So to show a purple pixel, our values would look something like Red(200), Green(0), Blue(200). Because we have 256 possible levels, that gives us a lot of possible colors to work with. To be exact, there are 256^3 possible colors.

The other way of storing color values is using indexed color. The two formats that use this on the web are 8-bit .png and .gif. These work by taking those 256^3 possible colors and then only choosing a subset of them to use in the image. These are then mapped to an index at the beginning of the file. So lets say we’re using a 16 color gif. Rather than needing to store the 24 bits of information for each pixel, only the index number needs to be stored. In our 16 color example, that is only 4 bits!

Which color representation is better?

 As you can imagine, there isn’t a correct answer. Different image types optimize better for different styles.

When you have images that contain a limited number of colors, you are better off choosing an indexed color type. Think about cartoons or screenshots of text. There aren’t many colors in these situations and often using an indexed color format will be much better. You can tell if you don’t have enough colors available by looking for “banding” or “dithering”.

When you are working with photographs or images that contain gradients, you are often better off with a 24-bit format. This will give you more colors to use.

How are images compressed?

 So our image is a collection of pixels, each pixel being a color. In the very worst case situation, all of the pixels are random and unique, so we have to save the value of every single pixel. But what if our image contains patterns? If our image is just a solid rectangle that is one color, you can imagine that we don’t need to save every single pixel. There are two main types of compression that get used on the web:

Lossless compression: This type of compression preserves the exact correct pixel. In a way it works like indexed color. It searches for repeating patterns in the image and gives those an index value. So rather than saving something that repeats multiple times, it just saves it once to an index, and then makes a note every time it repeats. When using lossless compression, you won’t be able to tell the compressed image from the original.

Lossy compression: Lossy compression does exactly what it sounds like. It throws away data. The compressed image is different from the original. This sounds terrible, but in practice it can work great. It works by looking for areas in an image that are close in color and it blurs away the detail. A classic example would be a photo that contains a bunch of blue sky. There might be bits of randomness in the sky, but you typically won’t notice it if that gets blurred away since the sky is very uniform. Lossy compression can also uses some of the same indexing tricks that lossless compression uses, but it can have the advantage of doing the blurring first to massage areas into looking the same.

Which compression method is better?

 Like color representation, there isn’t a correct answer. Lossless compression will work better on images that contain repeating elements. It does a poor job with noise, randomness and photographs because these often don’t contain things that repeat. Lossless compression will never look bad, it will just result in large image sizes.

Lossy compression does a poor job when it is absolutely important to maintain detail. You can tell when lossy compression is failing when images start to look blocky; this is called “artifacting”. Use lossy compression when lossless results in images that are too large and there aren’t noticeable artifacts.

Transparency

 Often you’ll want to place an image over a background and let that background show through. To do this requires transparency. There are two types of transparency, 1-bit and 8-bit. 8-bit transparency means that an an additional value, 0-255 is stored with each pixel. As you can imagine, this can make file sizes much larger since 33% more information gets stored per-pixel.

1-bit transparency means that a pixels is either completely transparent or it is a color. This is only used in combination with indexed colors.

24-bit transparency works exactly as you would expect. Things like dropshadows look great. 1-bit color can be a bit weird. It only works perfectly if there are clean, hard edges on the image. Otherwise you’ll be able to see the transition point between the image and the background. One trick to avoid this is to apply a matte color to the image so it appears to blend with the background. This only works when the image is going to be over fairly uniform background.

Putting it all together: a look at the web formats

JPG (24-bit color, lossy, no transparency)

 JPG can work great for images that are photographs or that have photographic-type detail that can be compressed away. It also works well in images that have a lot of gradients or shading. It does create artifacting which can be particularly noticeable on clean lines or text.

8-bit PNG (Indexed color, lossless, 1-bit transparency)

 This is a great first option to try for non-photographic images. If you can get away with 8-bit pngs, go for it since they compress very well and are lossless. If your image has a lot of gradients, or shading, the 256 color limit can be an issue. You can tell if your gradients contain bands or images look like they are filled with dots. If you’re working with transparency against a solid color, it can work great, otherwise the single bit transparency can be an issue.

24-bit PNG (24-bit color, lossless, 8-bit transparency)

 This is the only web format that has 8-bit transparency. It should be used when the image doesn’t look good as an 8-bit PNG or if full 8-bit transparency is required. It often compressed very poorly so in a sense it should be used as a last resort. Additionally, older versions of internet explorer cannot display them without some hassle.

GIF (Indexed color, lossless, 1-bit transparency)

 Gif is the same as 8-bit png but it uses a different (worse) compression algorithm. Don’t use it unless your project has weird requirements about using gifs.

Conclusion

While there is no one type of image that should be used in all scenarios online, there are definite guidelines that can help you maintain a quality image without unnecessarily slowing down the webpage's load time. Understanding the differences between different image types will help you make accurate decisions when it comes to deciding what kind of images to use when designing your website. 

 

Images from FreeDigitalPhotos.net artists: Salvatore Vuono, Simon Howden and Arvind Balaraman

Our Optimal ExpressionEngine Install

21 Comment(s) | Posted | by Josh Lockhart | |

First off: Yes. This is a post about another Content Management System on the HiFi Blog.

We developed HiFi in a way that best fits our clients’ needs. However, occasionally, it just isn’t possible to use a hosted solution for a client — particularly educational institutions and some government organizations. When our clients need a self-hosted content management solution, we rely on ExpressionEngine. As people who obviously have strong opinions on content management, we respect the way EE works and the ideas behind it.

We are very particular about our work — our projects must be written to the highest standards using W3C compliant markup and, at the same time, still remain completely faithful to the project’s original design. This is certainly not an easy task, and we require that any CMS we use makes this possible.

This post explains how we set up ExpressionEngine, from hosting, to plugins, to client hand-off.

ExpressionEngine Control Panel

ExpressionEngine is a mature and extensible content management system from EllisLab that is installed on your own web server. It is very customizable and allows us to develop and launch websites that are standards compliant and true to their original designs. We also like ExpressionEngine for its:

  • Mature plugin marketplace
  • Easy, clean templating system
  • Custom field sets
  • Customizable UI for client users

Although ExpressionEngine is perfectly capable on its own, we believe it is important to extend ExpressionEngine with several very useful third-party plugins. These plugins extend the functionality of EE, but perhaps more importantly, they critically improve your clients' user experience:

We’ll go into detail for each plugin below.

It’s important to remember the cost of these plugins in addition to the cost of ExpressionEngine when quoting projects for a client. For a commercial site, this comes to $299 for EE plus $164.90 for plugins, for a grand total of $463.90. When working with clients on a tighter budget, we will sometimes spread the cost out with their hosting payments during the first year. This comes to about $39 a month on top of hosting and backup.

Of course, ExpressionEngine does have its shortcomings when compared to a hosted content management solution: ExpressionEngine requires you to obtain a hosting account, create a database, install the CMS, add and configure plugins, harden security settings, optimize the website templates, and prepare the CMS for client users.

As I’m sure most ExpressionEngine developers will agree, setting up an ExpressionEngine website is not always a simple or quick task. But when done well, the end result is very rewarding. This article explains New Media Campaigns’ process for launching a custom website using an optimized ExpressionEngine installation. We’ve found that it takes an hour or two to get up and running and then another hour to prepare the CMS for client handoff.

Starting a Project

Before we start a project, we make sure the required software and tools are available on the production server. If you don’t check these early in the project development cycle, you are in for a rude awakening just prior to launch!

We rarely develop a project on the production server, so not having these items does not impede development (assuming your development environment has them). But you should check these items before you begin development to avoid complications when your deadline looms.

Web Server

We prefer a UNIX or Linux production box (or virtual machine) running the Apache web server. Other web servers like nginx or IIS will work, too.

SSH and SFTP

You’ll need a way to upload ExpressionEngine and change file permissions. SFTP access is a must. SSH access is even better.

MySQL

You’ll need MySQL 4.1 or newer. Make sure your MySQL database user has SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, and DROP privileges. These are required by ExpressionEngine.

PHP

You’ll need PHP 5.0 or newer with at least 16M of allocated memory. PHP will also need the GD2 or ImageMagick libraries if your application will use CAPTCHAs, image resizing, or image watermarking.

Installing ExpressionEngine

Installing ExpressionEngine goes smoothly once you’ve got your server environment set up. The EE site documents this well. There are five steps followed by an automated installation wizard.

ExpressionEngine Plugins

After ExpressionEngine is installed, the first thing we do is complement ExpressionEngine’s default features with several helpful plugins.

Structure ($65)

Structure is perhaps our favorite ExpressionEngine plugin. It provides a different (and more intuitive) paradigm for separating content from presentation compared to what ExpressionEngine provides out-of-the-box. The Structure plugin presents website content to our clients as a tree outline; it makes it easy to understand, add, edit, and remove site content. This is a concept we believe very strongly in which is why we use it in HiFi.

We’ve found that clients have a much easier time finding and editing their own content using this type of content representation. It matches the way they think about their site and the way we collaborate with clients to build a sitemap as a part of our creative process.

NSM Better Meta ($49)

Search engine optimization is very important to our clients, as it should be. The way a site performs in search engines and delivers returns to a client’s bottom line is a key way that we are measured as web professionals.

Leevi Graham’s Better Meta plugin provides an easier, more intuitive way for our clients to enter metadata (Title, Description, Keywords, etc.) for EE site content. Important SEO fields are added to the Publish Form where they really belong. Additionally, this plugin also automatically generates a sitemap.xml file for Google and other search engines.

WygWam ($35)

Although our developers prefer Markdown for writing page content, it is silly to assume our clients do, too. Most of our clients are familiar with and prefer using Microsoft Word and we want to make it as frictionless as possible for them to control their site. Therefore, it is very important to provide a familiar in-browser experience, integrated into the CMS, that makes a best effort to produce standards compliant markup.

WygWam, a plugin by Pixel and Tonic, does just that. WygWam integrates the popular CKEditor with ExpressionEngine and allows our clients to edit pages and other content using an in-browser rich-text editor akin to Microsoft Word.

FreeForm and FreeForm Spam (Free)

Many of our clients’ websites use online forms to collect all kinds of information. It is important that the CMS be able to collect and store user-submitted information. ExpressionEngine provides a very simple Contact Form implementation out-of-the-box. But FreeForm, a plugin by SolSpace, does a much better job.

FreeForm allows us to define an unlimited number of Form variables and Form templates that are used to capture user-submitted data and send templated notification emails to both the submitter and the receiver. Strongly consider installing FreeForm with FreeForm Spam to help reduce spam submissions.

Image Sizer (Free)

Perhaps one of the most popular ExpressionEngine plugins, Image Sizer allows you to dynamically resize and cache images on-the-fly as they are requested. This turns out to be a very important tool in improving the experience your clients have with their site.

This plugin ensures images fit your design regardless of the original images uploaded to the CMS by the client. While it might be a big deal for those of us that do this for a living, dealing with image dimensions, aspect ratios and resizing is a big hassle for most people. Installing this plugin will make your clients’ lives easier and give them a lot more confidence to go in and edit their site.

CP Analytics (Free)

As its name suggests, the CP Analytics plugin presents the website’s Google Analytics data on the ExpressionEngine CMS dashboard. This allows our clients to quickly see how their site is reaching their customers and constituents.

NSM .htaccess Generator ($14.95)

This helpful ExpressionEngine plugin, also from Leevi Graham, removes the “index.php” from ExpressionEngine CMS page URLs to create more user-friendly page URLs. This plugin is more an aesthetic preference than a necessity.

Securing ExpressionEngine

ExpressionEngine, out-of-the-box, is quite secure. However, there are several additional steps you can take to further harden ExpressionEngine website security.

Secure your server

If you are managing your own web server, you can require key-based login and disable password-based login. This is perhaps the most beneficial security precaution you can take.

Secure your database

If your MySQL server is running on the same machine as your web server, only allow connections from localhost. This prevents potential remote attempts to hack your database.

Rename the system directory

When you install ExpressionEngine, you have the opportunity to rename your ExpressionEngine system directory. Using a different name from the default value will provide a little bit of additional security through obfuscation.

Move your system directory above the web document root

Should your web server configuration become corrupted or malformed, PHP files beneath your document root could potentially be served as plain text. Moving your ExpressionEngine system directory above your document root ensures sensitive information is not inadvertently disclosed.

Process form data in Secure Mode

Processing form data in secure mode deters automated spam submission attacks. It does add one additional database query, though.

Disable “Allow Dictionary Words as Passwords”

This prevents users from using plain-text dictionary words as account passwords. Inconvenient, maybe. Secure, yes.

Consider Using CAPTCHAs

ExpressionEngine can generate and require CAPTCHAs for all form submissions. This will help prevent spam. You can enable and configure CAPTCHAs in “Admin > System Preferences > Captcha Prefences”.

Additional security preferences

You can read more about ExpressionEngine’s numerous security preferences in the online User Guide.

Optimize ExpressionEngine for Performance

ExpressionEngine will perform admirably by default. However, should your website be Fireballed, there are a few additional tweaks you can make to improve ExpressionEngine’s performance.

Query caching

When Query Caching is enabled, ExpressionEngine will log database queries to a text file. When the same query is performed, and if a related cache file exists, the cache will be used instead of calling the database. You can enable Query Caching at “Admin > System Administration > Database Settings”.

Note: It was brought to my attention in the comments that Query Caching is disabled by default and discouraged by EllisLab; native MySQL caching is much faster than using PHP for query caching. But this feature is available if needed.

Fragment caching

Expression templates support fragment caching. Simply add the “cache” and “refresh” attributes to any ExpressionEngine template tag. The “refresh” attribute value is an integer (measured in minutes), and the content of the given tag will be cached for the specified length of time. Fragment caching is preferable when you need to cache parts of a page that contains other dynamic data that may change with each request.

{exp:channel:entries channel="news" limit="10" cache="yes" refresh="10"}
    This content will be cached for 10 minutes
{/exp:channel:entries}

Template caching

If you prefer a more heavy-handed approach, you can cache entire pages. You can enable Template Caching and specify the refresh time period in the Templates page’s preferences panel. It doesn’t make sense to use both Fragment Caching and Template Caching together for the same page; choose one or the other but not both.

Disable unnecessary query data

When you output channel data using the {exp:channel:entries} tag, ExpressionEngine will query for a lot of information by default; some or most of the queried data may be unnecessary. You can disable certain query data to improve the performance of this tag. The items you can disable are:

  • categories
  • category_fields
  • custom_fields
  • member_data
  • pagination

To disable any of the above items, add a disable attribute to your Channel Entries tag and separate each item name with a “|” pipe.

{exp:channel:entries disable="categories|member_data|pagination" ... }

Perform Front-End Optimizations

While not specific to EE, it is important to optimize your template code so that the site can perform its best. Generally this means following guildlines like YSlow or Google PageSpeed and testing either in Firebug or with something like GTMetrix.

A trick for making this process easier is to automate the minification and compilation of all of your css and js. We really enjoy having this functionality in HiFi. A beta EE plugin for this is Minify.ee by Leevi Graham. His other work is great so we expect this to be as well.

Prepare ExpressionEngine for Clients

By this point in the project, we have installed ExpressionEngine, purchased and installed plugins, hardened security, and optimized the CMS. The project is nearly complete and ready to deliver to the client. Before we do, though, we need to do some house-cleaning.

Create a “Clients” member group

First, we create a new Member Group specifically for the client. This allows us to expose only certain elements of the ExpressionEngine CMS to our clients.

ExpressionEngine Member Groups

Create a new Member Group called “Clients” at “Members > Member Groups”. Then, still on the “Members > Member Groups” screen, click “Edit Group” for the “Clients” member group. The most important settings we use for simplifying client access to the EE CMS are:

  • Control Panel Area Access
    • Can access PUBLISH page (YES)
    • Can access EDIT page (YES)
    • Can access TEMPLATES page (NO)
    • Can access COMMUNICATE page (YES)
    • Can access MODULES page (YES) †
    • Can access ADMIN page (NO) ††

(†) Although the client can access this panel, it will be hidden from view
(††) You may want to enable this depending on your client’s needs

There are many other access settings you can configure based on your client’s needs. If you will have many client users of various roles (ie. editor, department-specfic, etc.) it may also be necessary for you to edit the “Channel Assignment” settings for each client user to only give client users access to certain ExpressionEngine channels.

Simplify page editors

If left with default settings, ExpressionEngine channel page editors will have a lot of tabs and a lot of settings — some of which may be unnecessary. We recomend you make the UI as simple as possible with only the controls that clients need to manage their site.

ExpressionEngine Page Editors

On the “Admin > Channel Administration > Channels” screen, for each channel, click “Edit Preferences”. The most important settings we use for simplifying channel editors for clients are:

  • Administrative Preferences
    • Default Status
    • Default category
    • Select “Allow Comments” button in Publish page by default?
  • Channel Posting Preferences
    • Automatically turn URLs and email addresses into links?
  • Comment Posting Preferences
    • Allow comments in this channel?
    • Enable Captcha for Comment Posting?
    • Moderate Comments?
  • Layout Customization in Publish Page †

(†) Uncheck the items that are not needed for the client to edit content in the given channel.

On each Channel’s New Entry form, we also click “Show Sidebar” and hide unncessary tabs and fields.

Customizing each user’s Control Panel

And last, we customize each user’s Control Panel. To do this, we log into the Control Panel as each user and perform the following changes:

  • Add a new “Pages” tab that links to the Structure Module page
  • Add a new “Forms” tab that links to the FreeForm Module page

You can add additional tabs if you need to provide easy access to other Modules. Because of the changes performed in “Create a clients member group” above, the client user account should not see the “Templates” and “Admin” tabs. Our goal is to provide a simple user interface that only provides the tools required by the client — nothing more.

Moving to the production server

After the client approves the website, it is time to move the website to the production server. After you migrate your database (if necessary), you need to move over the ExpressionEngine CMS files. When you do, ensure file and folder permissions are still correct. You will also need to edit several path settings in the ExpressionEngine control panel.

Log into the ExpressionEngine Control Panel on the new server. The Control Panel styling and images will likely be missing.

General Configuration

ExpressionEngine General Preferences

Navigate to the “Admin > General Configuration” screen and edit the following fields:

  • URL to the root directory of your site
  • URL to your Control Panel index page
  • URL to your “themes” folder

Captcha Configuration

ExpressionEngine CAPTCHA Preferences

If the project uses CAPTCHAs, navigate to the “Admin > Security and Privacy > Captcha Preferences” screen and edit the following fields:

  • Server Path to Captcha Folder
  • Full URL to Captcha Folder

File Upload Preferences

ExpressionEngine File Upload Preferences

If the project accepts file uploads, navigate to the “Admin > Content Administration > File Upload Preferences” screen and edit the following fields for each File Upload Destination.

  • Server Path to Upload Directory
  • URL of Upload Directory

Template Preferences

ExpressionEngine Template Preferences

If the project saves template files to the filesystem, navigate to the “Design > Templates > Global Preferences” screen and edit the following fields:

  • Basepath to Template File Directory

Provide clients with a “How-To” guide

When you hand-off an ExpressionEngine website to a client, you may have included one-on-one training in your contract. If not, it will be helpful to provide the client with the resources to learn and use ExpressionEngine to edit his website. A great resource for clients is the HeadSpace Client Guide (PDF) for ExpressionEngine 2. This guide provides an easy-to-read overview of how to use ExpressionEngine to edit website content.

http://headspacedesign.ca/blog/entry/the-expressionengine-2-client-guide-is-here/

Hopefully this guide has been a helpful look into the process that we go through when we set up an ExpressionEngine site. By taking our time and ensuring that we configure and install everything necessary, we’re able to deliver a high performing site that our clients are able to manage.

First we built an API, then we built a CMS

6 Comment(s) | Posted | by Kris Jordan | |

API design has been a point of discussion on Hacker News recently. The discussion has been focused on the process of adding on an API to your app. With our SaaS product, the HiFi CMS, we approached the problem from the opposite direction: flesh out the API first and then build your application on the API. There was a lot of interest in our approach to this, so we thought we would write out this post.

Our application, HiFi, is a modern web cms that is the antithesis of most cookie-cutter CMS SaaS products on the market. A core goal with HiFi has been to create a platform where professional designers, web developers, and information architects can create websites that live up to their original vision. Early in the planning process it became clear a flexible, first-class API would be needed to achieve this goal. Getting the API right would be the only way a hosted CMS could acheive the flexibility that developers love about non-hosted platforms.

Our requirements for the API were driven by common sense best practices and by the unique needs of website content models. The key requirements were:

  • Consistency - all objects in the system should be represented, manipulated, searched, versioned, and access controlled in the exact same way. This holds for content, types, users, relations, permissions, etc.
  • Simplicity - there are only two methods in our API: get and put. An object's type and its "undeleted state" are just properties of each object. JSON is the only format for V1. Further more, the requests made are in a very similar format to the data you get back. It just feels natural.
  • Versioning / Immutability - storage is cheap in 2010: why not keep everything? Objects aren't updated or deleted, new copies are created.
  • Structure - all objects are organized in a tree. Relationships between objects can introduce additional structure.
  • Queryable - all objects can be queried by criteria on their own properties and properties of structuraly related objects
  • Access Controlled - read / write permissions can be applied to any object and inherit down the tree

We built the API to satisfy these requirements first, then we built our app on top of the API. This turned out to be a great idea. We got to dogfood our API for the entire development process and it made testing a lot simpler.

Websites running on HiFi use a templating language, twig, which is very similar to Django templing. All templates have access to the API server-side. This makes it really easy to add complex features to websites without much stress. Here are a few quick examples of queries:

{"type":"page", "orderBy":"-publishedAt"}

This query pulls in the most recently published pages in HiFi.

{"type":"page","orderBy":"-publishedAt","parent":{"type":"feed","url":"/blog"}}

Fetch the most recently published pages whose parent is a blog feed with url '/blog'.

{"type":"page","orderBy":"-publishedAt","child":{"type":"comment"}}

Fetch the most recently published pages which contain a comment.

All nested queries can be combined as much as possible and be as recursive as desired. There are similar commands for working with relationships. The net result is an API that was simple, yet powerful enough to build our admin panel on.

HiFi UI

HiFi's admin user interface is 95% client-side using jQuery, Resig's JavaScript templates, and pulls data via the API. We created a HiFi JS library that creates a jQuery-like chainable DSL around the API. The next example should look familiar to jQuery users. In it we'll change the URLs of all pages on a site to be lower case using this:

hifi({type:'page'}).each(function(page) {
    hifi(page).update({url:page.url.toLowerCase()});
});

A neat side-effect of writing the API first is finding use cases you didn't plan for. One example for HiFi was in keeping old versions of all objects. The intention for this API feature was to enable easy roll backs for any content type. When we recognized that old URLs were being stored and were queryable through the API we updated our website routing code's logic to see if an unreachable URL ever existed and if so we automatically 301 redirect to the object's most recent version's URL. We got this for free. Had we built the app first we would have written a lot of special case code to achieve the same result.

Now that HiFi is open for business and over 50 websites have launched on the service we're beginning to see uses of the API in end-user work that are really exciting. An example site that has personally blown me away is PBS' CiaoItalia.com. Ciao Italia is America's longest running cooking show. Over the course of 21 seasons chef Mary Ann Esposito has compiled a lot of great recipes and videos. If we were to flatten the APIs tree it would look like: 21 Seasons -> ~20 Episodes each -> ~4 Recipes each -> YouTube Video. This advanced search page was implemented entirely using the API in user-space templates.

HiFi's API was built before we built the app on top of it and it's a better product because of it. If you're not in a greenfield situation and your app already exists consider what it would take to design an API that could eventually sit beneath your app not beside or on top of it. Investing in a great API not only cleans up your code base, but also opens up the door for awesome, unanticipated use cases coming to life.

How to Use JSON APIs with jQuery

8 Comment(s) | Posted | by Joel Sutherland | |

One of the best features of jQuery is its simple AJAX functionality. This allows you to easily pull data from other sites and services onto your own site. Learning how to use this functionality makes it easy to integrate any number of services into your websites, making them richer and more interesting to your visitors. It will also make you less dependent on the widgets that companies provide, allowing you to create your own.

jQuery JSON APIFor this post, I am going to show how I created URL Tweet Compete, a tool that allows you to enter multiple urls into a textarea, and it then returns the number of tweets that the they have on Twitter. Be sure to try it out so that you can understand what this post is all about.

The tools uses the Topsy Otter API. This is a fun API to play around with because it is easy to understand and it doesn't require any authentication.  Additionally, it supports jsonp which is important as I will explain later.

The core call in jQuery for this project looks like this:

$.ajax({
    url: "http://otter.topsy.com/urlinfo.js?url=http://www.nytimes.com",
    dataType: 'jsonp',
    success: function(results){
        console.log(results);
    }
});

Now lets get in to the mechanics of how this works.

What are APIs? What is AJAX?

This might be old news, but it's worth covering quickly. You could read all day about APIs and AJAX, but they are also easy enough to understand in concept.

An API is a tool that makes information available to progams in a more convenient format.  As an example, humans can go to Twitter's website in their browser to see a pretty display of tweets.  The Twitter API however presents the tweets in a way that is convenient for programs.  It just gives the info.

AJAX is a phrase that roughly means "fetching information on a loaded page using Javascript".  It is an acronym with a specific meaning, but it is now used more generally.  The "X", for example, stands for XML, but now AJAX is used whenever there is any kind of dynamic content is being displayed, including JSON. Typically, AJAX is used in conjunction with an API.

So how does it work?

In the example above we are initializing an AJAX request to the Topsy API. You can see exactly what happens by checking out the URL yourself, directly: http://otter.topsy.com/urlinfo.js?url=http://www.nytimes.com As you can see, the following is shown:

ajax response

So when that request is made, some data is sent back. We're now able to use this data however we like on the page.  In the case of the URL Tweet Compete app, we're displaying the "trackback_total" value which represents the total number of tweets that have been received.

What is JSONP?

When making AJAX requests to external domains, there are a number of restrictions that apply for security reasons. JSONP is a technique to get around these restrictions. jQuery builds it into their $.ajax() method to make it easy to use.

Whenever you're using an API that is hosted on another domain, you'll need to make sure you're using the jsonp version of the API. Topsy offers an XML, JSON and JSONP version. A common mistake is attempting to use the JSON version which is impossible with javascript on another domain.

With Topsy (and many other APIs), you can select which version you want by changing the extension on your request.  For the XML version, use ".xml", for the JSON version use ".json".  Usually to get the jsonp version, you'll use either ".jsonp" or ".js".

Putting it All Together

So in order to request information from the Topsy API and display it on a page, you'll need some code like this:

$.ajax({
    url: "http://otter.topsy.com/urlinfo.js?url=http://www.nytimes.com",
    dataType: 'jsonp',
    success: function(results){
        var title = results.response.oneforty;
        var numTweets = results.response.trackback_total;
        $('#results').append(title + ' has ' + numTweets + ' tweets.');
    }
});

This code goes and fetches information about the url: http://www.nytimes.com and then displays the number of tweets it has.  Notice that we're doing the displaying within the 'success' function.  This is because we don't get the information back from our Topysy AJAX request immediately.

Instead, once it comes back, jQuery calls the success function that we define and passes in the results so that we can use them.

Hopefully this post is helpful for those new to using APIs and AJAX.  If there are any questions or comments, please leave them below!

A Boilerplate for CSS Typography

1 Comment(s) | Posted | by Joel Sutherland | |

CSS Typographic Baseline

See the Demo | Download the Zip

Writing the CSS for websites can be a very time consuming process. There are often big things that need to be done when creating stylesheets like layout, that leave a developer exhausted when it comes time to handle the details. One detail that is often overlooked is ensuring good coverage of all typographic elements as well as setting up a clean typographic framework.

This is especially an issue when setting up a site on a Content Management System.  As new content is created, it is important that the CSS developer has anticipated all of the elements that will show up on the site and set up rules for them. By my count, there are over 20 elements that need to be considered in a variety of combinations.

Using a solid boilerplate foundation can make this task much easier.  For that reason, I've developed a CSS Typography Boilerplate that I use to ensure coverage of all elements. As a bonus, using this as a starting point makes it really easy to set up a typographic baseline grid.  This post covers this boilerplate, explains what a typographic baseline is and gives you the stylesheet you can use as a starting point.

What is a Baseline Grid?

Typographic Baseline GridWhen taking about grids and the web, we're usually talking about vertical columns.  A typographic baseline grid establishes a vertical order, rhythm and spacing for your text that aligns with a grid.

The idea is to set the font-size, line-height and margins of all of your typographic elements, such that text automatically fits into a grid.

This might seem like overkill, but it is a great way to ensure that the content type on a page looks great. By no means, do I advocate the strict adherence to a grid though. Often it makes sense to break the grid or to not use a grid at all.  I do however, think that using a grid is a great starting point for most sites.  Additionally, I've found that starting with a grid and modifying from there is a big timesaver. 

To see this project's starting grid in action, check out the demo.

How to Use this Boilerplate

This project includes a zipped directory of a good type starting point.  There is a good html-ipsum that contains greeked text showing nearly every element you need to cover.  Additionally there is a typography.css file that contains the rules for each element in a fairly organized fashion.

By default, all rules are preceeded with ".content".  This is to make it easy to apply this stylesheet to a particular container.  If you want to use it globally, which I recommend, just do a search replace to kill all instances of ".content".

/* Block Baselines */
.content h1, .content h2, .content h3, .content h4, .content h5, .content h6,
.content p, .content ul, .content ol, .content pre, .content blockquote {
    margin-bottom: 20px;
}

When configuring this stylesheet for your site, there are three primary rules to consider: font-size, line-height, and margin-bottom.  Keeping these consistent or mindfully changing them is the best way to keep the grid.  By default, copy is 12px on a 20px grid.

I've also included a set of rules to display the grid on a container class as well as give a background to all block elements.  This is great for debugging when you really want to hit the grid exactly.  The rules look like this:

/* Baseline Debugging Backgrounds */
.showBaseline {
    background: url(../images/baseline-20.png);
}
.showBaseline h1, .showBaseline h2, .showBaseline h3, .showBaseline h4, .showBaseline h5, .showBaseline h6,
.showBaseline p, .showBaseline ul, .showBaseline ol, .showBaseline pre, .showBaseline blockquote {
    background: rgba(255,200,200,.3);
}

If you want to use a baseline of a different height, just make a 1px wide image of the height you need with the bottom pixel filled in.

A Sidenote on Using Pixels

Starting some time ago, the use of pixels for font-sizing has been making a comeback.  To give a quick recap, pixels were basically abolished as a best practice because IE6 and older did not give the option to rescale pixel-sized text. Beginning with IE7, IE has allowed for page-zoom style scaling.  As IE6 has lost significant browser share, pixels have become a viable option for sizing text again. I am 100% for this and that is why you see pixels in this boilerplate.  I do plan on releasing a version that is not dependent on pixel sizing at some point. (If a reader wants to give a hand with this it would be appreciated!)

To read more about this debate, here are some good articles:

Demo and Download

Last updated: 11/12/2010

Release Notes:

  • <select> breaks the grid.  Not sure what to do about this.
  • No default styles for tables yet.

If you have any questions, comments, or improvements, be sure to leave them in the comments.

Accepting Applications for Private Beta

2 Comment(s) | Posted | by Clay Schossow | |
The long awaited day is here.  After a year of building, testing, and refining, HiFi is entering a private beta.  While we have put more than twenty of our own client sites on the system, we have not previously opened it up to outside developers.  We learned a lot from our own clients and how they used the system -- after making tweaks based on their feedback and resolving bugs they ran into, we're ready to open the system up to the rest of the world.

While we had originally hoped to enter this phase earlier in the year, we didn't want to rush the product and release something that wasn't fully ready to be used.  To us, a complete and polished system is the minimum viable product that you would expect from a CMS.

Fill out an application here to join the beta.  We're screening applications to make sure we get a wide breadth of users and projects, and to make sure HiFi is the best fit for what you're working on.  We'll begin rolling out beta accounts to selected users at the end of the week!

Beta accounts will be free to selected applicants.  Beta users will have access to the standard HiFi  setup, including unlimited access to the CMS, full use of the API and templates, and hosting of the site on HiFi's dedicated server (includes daily offsite backup, RAID, 24x7 uptime monitoring by pingdom, and more).

We really think that HiFi is a phenomenal product, representing a new type of CMS for developers.  Here is just a short list of some of the features ready for you to take advantage of:

We'll be posting more on each of these features in the coming weeks.  We've been having great success using them for our own clients, but are excited to hear feedback from the beta group.

We want to thank everyone for their patience while we've been building a system that we know will be a welcome addition to the web publishing space.  Your support and dialogue has been extremely helpful in pushing this project to beta.
 
Now, go sign up, get a free account, and enjoy!

 

A jQuery Flickr Feed Plugin

100 Comment(s) | Posted | by Joel Sutherland | |

View the Demo | Download the Zip

We often work with clients that maintain accounts with Twitter, Flickr, Youtube and other services in addition to their website. Often they will want to pull in data from one of their accounts to their website.  With Flickr, this is pretty easy because they make a simple API available.  Having worked with it a few times, we decided to make it even easier to pull photos from a public feed.

flickr dogs

There are a few examples of this in use on the demo page.  All of the photos on this page have been used with the generous permission of John Roberts (@jroberts13).

Plugin Overview

This plugin works by pulling a JSON feed from Flickr and applying the data it gets back to a template.  For example, we can generate this list of pictures:

<ul>
	<li><img alt="Photo Title" src="http://farm4.static.flickr.com..." /></li>
	<li><img alt="Second Photo Title" src="http://farm4.static.flickr.com..." /></li>
</ul>

From the following jQuery:

$('ul').jflickrfeed({
	limit: 2,
	qstrings: {
		id: '44802888@N04'
	},
	itemTemplate: '<li><img alt="{{title}}" src="{{image_s}}" /></li>'
});

The plugin gets the feed from Flickr using AJAX and applies each image it gets back to the provided template.

The Plugin Options

There are a number of options available on the plugin, these are the defaults:

flickrbase: 'http://api.flickr.com/services/feeds/',
feedapi: 'photos_public.gne',
limit: 20,
qstrings: {
	lang: 'en-us',
	format: 'json',
	jsoncallback: '?'
},
cleanDescription: true,
useTemplate: true,
itemTemplate: '',
itemCallback: function(){}

Here is a description of each one:

  • flickrbase: This is unlikely to be needed.  It is used to set up the url the jQuery AJAX call will need to be made to.
  • feedapi: There are a number of feeds that flickr makes available.  The default is the public feed.  Here is the list of all that are available: http://www.flickr.com/services/feeds/. This has only been tested on feeds that return photos.  So, for example, don't expect good results using this plugin on the Forum discussion feeds.
  • limit: Set how many items you want to loop through.  Flickr seems to limit its feeds to 20, so that is the default.
  • qstrings: This is the most important setting. This is used to request the correct feed.  In my examples I use this to set the user id.  These are automatically added to the request url. Depending on which feed you use (http://www.flickr.com/services/feeds/) there are different sets of query parameters available: http://www.flickr.com/services/feeds/.
  • cleanDescription: Flickr puts all kinds of junk in the description it returns. By default this plugin is set to remove everything but the plain photo description.
  • useTemplate: Set this to false if you don't want to use the plugins templating system.
  • itemTemplate: The template rules are described below.
  • itemCallback: You can add a callback on each item.  The scope is set to the container and the item object is made available.

Typically, the only things that will need to be set are limit, qstrings.id and itemTemplate.

Using the Templates

In order to make it really easy to use any kind of markup needed with this plugin, a simple templating system has been build in.  Here is an example of a template:

<li>
	<a href="{{image_b}}"><img src="{{image_s}}" alt="{{title}}" /></a>
</li>

You can see that this is just basic html with a few special tags mixed in.  All of the tags are surrouned by double curly braces. The plugin works by putting in the correct information for each tag and each item into the template.

The tags that are available depend on what flickr returns for each item.  For the Public Photos API these are: title, link, date_taken, description, published, author, author_id, tags, and image.  For the image property, the plugin uses the Flickr URL scheme to make several sizes available.  You can read about this at http://www.flickr.com/services/api/misc.urls.html.  The image tags available are: image_s, image_t, image_m, image, image_b.

The Callback Parameter and Integration

The plugin's second parameter is a callback.  This has the scope of the containing element and has the entire data response available. This is a great feature if you want to integrate this plugin with others.  Let's say you want to integrate it with colorbox. If you call $('selector').colorbox() and then this plugin it won't work.  This is becuase the plugin is adding elements to the page after the colorbox call.  This is even true if you call colorbox after this plugin.  Since this uses ajax, your images won't be added to the page until well after most of your javascript has run.  (In computer time).

Instead, the trick is to use the callback function.  This allows you to pass in code that you want to run after the images have loaded.  So for example, you can do this:

$('#cbox').jflickrfeed({
	limit: 14,
	qstrings: {
		id: '37304598@N02'
	},
	itemTemplate: '...example...'
}, function(data) {
	$('#cbox a').colorbox();
});
			

Now the colorbox call won't be made on the photos until they are loaded.

Demo and Download

You can see a demo of this plugin on the demo page.  Additionally you can download a zip of this plugin and the example.

As always, if you have any questions or comments, leave them below.  Enjoy!

AutoSprites - A jQuery Menu Plugin

46 Comment(s) | Posted | by Joel Sutherland | |

Update 1/22/2009 - This plugin now contains support for an active state. It is just as easy to use and all of the animation still works with it. Read below to see how it works. (This was originally posted 10/28/2009)

AutoSprites jQuery Menu Plugin

Download the Files (Zip) | View a Demo

We have written and released a jquery dropdown menu plugin as well as a CSS Sprites2 Plugin -- this post is along the same lines. Its purpose is to allow you to build an image-based menu with animated hover states as easily as possible and by using the most concise descriptions possible. To see the results on both a horizontal and vertical menu, check out the demo.

Setting up the jQuery Menu Plugin

The first component when doing something with sprites is a combined image that contains all menu states. For the menu above, this is the image below was used. (This was designed by Liaison Design Group, one of our Partners)

sprites

The image contains, the normal state, the hover state and the active state. The value to doing things this way is that it allows your site to load faster. Rather than downloading an image for each nav item its hover state and its active state, only a single image needs to be downloaded. This minimizes the overhead of many http requests.

The next thing to do, is set up the HTML for the nav bar:


Then we need to set up the CSS. There are a couple of things to note here. We are applying the background image to the containing element so that we don't need to respecify background positioning. This also makes the menu usable if javascript is disabled. Each element needs to have its size defined specifically as well.

#hnav { position: absolute; top: 0; left: 0; width: 615px; height: 72px; background: url('horiz_sprites.gif') no-repeat; }
#hnav li { position: absolute; left: 0; height: 72px; }
	#hnav #hnavhome { width: 82px; left: 0px; }
	#hnav #hnavlocal { width: 146px; left: 82px; }
	#hnav #hnavhigher{ width: 162px; left: 228px; }
	#hnav #hnavcomm { width: 143px; left: 390px; }
	#hnav #hnavnews { width: 82px; left: 533px; }
#hnav li a { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 72px; text-indent: -9999em; }

Notice how much less complicated the CSS is than what is typical with sprites. There is no need to define background positioning for each element and its hover state. The last piece you'll need to do is enable the autosprites plugin:

$(document).ready(function(){
	$('#hnav').autosprites();
});

There are no required options. The plugin defaults to a horizontal menu and fading for the animation. It infers everything else from the CSS. If you would like to customize things, here are the options that are available:

settings = $.extend({
	offset: '100%',
	orientation: 'horizontal',
	over: { opacity: 'show' },
	overSpeed: 500,
	out: { opacity: 'hide' },
	outSpeed: 500,
	activeState: false,
	activeClass: 'active',
	activeSprites: false
}, settings);

The only bit worth explaining is the active state. In the image above, I show three states. By default, you only need two, a normal state and a hover state. If you set 'activeState' to true, it will use the hover state by default. If you want to specify your own active state, simply set 'activeSprites' to true as well.

So that's it! You can specify the minimum amount of information about your menu and the sprites will be built automatically. Be sure to check out the demo and download the zip for your own projects. As always leave a comment if you have any complements, insults, suggestions or questions.

A Special Note on Compiling Javascript

The purpose of using sprites is to minimize HTTP requests. It would be foolish to use this plugin by including jQuery, the minimized plugin, and a setup script. Instead, it is best practice on a production site to bring all of your scripts together into one file, just as sprites bring your images into one file.