Barefoot Development

Designing emails for the inbox

At Barefoot, we help our clients with email marketing strategies and in doing so need to know the successes and pitfalls of HTML email practices. HTML email is arguably more difficult than HTML standards compliance in a browser. There are more email clients out there than browsers, and very few of the clients are held to any sort of standards compliance benchmarking.

For example, Lotus Notes may be great in some of the features it offers and corporations may really benefit from them. However it is absolutely terrible at rendering HTML email. Tables do not display correctly, especially when nested. However some email clients are starting to use the HTML rendering engines that their counterpart browsers are using. For example, Apple Mail uses the Webkit rendering engine that Apple's browser, Safari, uses. There may be small differences, but overall we know that HTML in the Mail client will look similar to what it looks like in Safari. The same could be said about Outlook and Internet Explorer to a degree.

However Mail clients don't support everything that browsers do, such as full JavaScript implementation, full CSS implementation, and most don't support full plug-in implementation.

Because of these things, designing an HTML email is not like designing an HTML file to be used on a Web site. We'll discuss some of the differences and key points below:
  • Use: Maximum width of whole message: 500 - 640 pixel wide table
  • Use: HTML Title in heading
  • Avoid: Hot red and blue colors
  • Avoid: Large font sizes
  • Avoid: Borders around tables
  • Avoid: Background color other than white. Some email clients ignore background color. If background color must be set change it in a <table>, not the <body>
  • Don't use Javascript
  • Don't use style sheets
  • Use absolute references to all web content: start with http://
  • Use only standard web fonts (Arial, Verdana, Times New Roman, etc.)
  • No DHTML Layers, use Tables instead
  • No image maps, use complete links on images instead
More technically specific points:
  • HTML should be written in HTML 3.2 and include the DOCTYPE declaration.
  • Include a charset in the header.
  • Keep in mind that HTML Headers get stripped when viewed in Web based email clients like GMail.
Other Links:

design + development = flash workflow

At Barefoot, we do a lot of Flash application development, everything from interactive Web sites with video to Flash based games. Flash projects typically take more time than traditional Web projects, simply because of the robust nature of the medium. Flash introduces motion and statelessness. Flash can certainly be more engaging than "page" based sites. However, because Flash adds more complexity, and usually time, it also adds more need for a solid workflow amongst team members.

No workflow process is ever complete. They seem to be constantly evolving, partially due to the fact that the technology is constantly evovling. Our workflows revolve around the team members and who starts the project files off. We have experimented with designers starting the project or developers starting the project. Let me explain further. One approach is to let the designers create the FLA and all of it parts, including layout, animation, and some interactivity, then handing off to the developer to tie everything together. The other approach has the developer architecting the application, creating the setup, pieces, and logic, and then handing off to the designer to work their magic on the individual pieces.

A couple of factors are key to the decision. Is your application going to practice Object Oriented Programming theory or more specifically a design pattern like MVC? Or is your application going to use procedural code where you could easily add logic along the timeline during key events, matching up with any motion or animation?

Here are some common scenarios and reasons why you would choose one workflow over another. If you were building a game, you would probably decide to practice OOP. Because of this reason, it would make sense for the developer to start with the project, architect the solution, set up the Classes, and any corresponding symbols. The designer could then work with the library symbols and add any graphics and motion to the piece. A key factor in the ability to do this is specifying the Class for any given symbol in the library, using either the "linkage" property and assigning the ActionScript 2.0 Class or through a process known as registering the object with a class.

However, say you were creating an online product demo. This demo, doesn't really have a lot of interactivity, more like events will need to fire during certain times throughout the demo. Because of this, procedural code can certainly fit the bill and may make development of the application easier. This scenario may lend itself to the designer initiating the project and identifying where logic needs to be added. Our designers know to create an actions layer and identify the first frame where all code will be added so hand off to a developer is very straight forward and logic can be added to this frame in functions and simply called throughout the movie.

Team members and their understanding of Flash is also very important. At Barefoot we are very lucky to have designers that also know a very good amount of ActionScript. Because of this we can be flexible in the workflow we choose.

Choosing one workflow for all projects may very well be impossible, so narrowing down the choices to just two may make agency life a whole lot easier. The more familiar your workflow becomes the faster you can deliver for your clients, bring new team members into the fold, and minimize the debugging in the middle.

Michael Krisher, Senior Developer, Barefoot

Automating Development Website Setup

Over the years, setting up development and staging environments for our websites had become a tiresome chore, filled with "opportunities" for typos. So one Saturday evening, I sat down, brushed the dust off my bash scripting skills and wrote a handy little tool for Barefoot. I know that there are other tools out there, but I found none that acomplished all of our goals:
  1. The tool should be interactive, rather than configuration-driven.
  2. The tool should enforce naming policies our company had put in place.
  3. The tool should integrate with Subversion, our chosen source control system.
  4. To help cut down on misconfiguration caused by typos, some sane defaults should be presented.
  5. The tool should automate the setup of both PHP-based and Rails-based applications.
  6. The tool should make developers' lives easier by pre-populating dev sites with Barefoot standard code libraries. Once the site has been prepopulated, a new Subversion entry is created for the new site.
I think that's probably enough to ask of any tool. The script is far too long to go through every line, so I'll just give an overview here, and then make the entire script available for download. It's pretty well commented.

Overview of what the script does, in the order it does it:
  1. Ask the user to enter a new hostname, check it against or naming policies using regular expressions. Fail with useful error if needed.
  2. Ask the user to enter the domain name, give the user a sane default (thinkbarefoot.com), and check it using regular expressions. We separate the hostname and the domain name becuase Barefoot's standard directory structure for Apache-based sites is /www/domainname/host.domainname. Whenever we say we're giving a "sane default" we mean that the user can simply hit the enter key to select it.
  3. Choose an FTP username and password for the dev site. GSD, FWUEIN (give sane default, fail with useful error if needed).
  4. Choose a Subversion repository name. Check it against our naming convention. GSD, FWUEIN.
  5. Choose either a Rails-based project or PHP-based.
  6. We have a "skeleton" directory for each of the two development types. Depending which one is chosen, we create a new user, make that user's home directory be the result of #2 above, and populate that home directory with the contents of the correct skeleton directory.
  7. Add a new virtual host to the Apache configuration. The correct entries are put in place for each of the two project types. This is done using sed to take a template file we've created for each and replacing the info gathered above.
  8. Next, we check out our standard librabries from Subversion and place them in appropriate places in the new directory structure.
  9. Now that the new site is put together, we wrap it all up into the Barefoot standard directory structure for Subversion, and check the new module into our Subversion server. Keen observers will note that we use the password-less authentication for SSH discussed in our blog here.
  10. Finally, we set the correct ownership on the files and clean up some extraneous directories made simply to make a nice Subversion module.
  11. As the script exits, it reminds the user to add the new host to our internal DNS and spits out the login information for easy copy and paste into your preferred login notes.
While this hasn't revolutionized our lives, it has certainly cut down on the time spent setting up new development sites. By using a couple of choice templates, skeleton directories, and Subversion we've been able to keep our setup much more consistent.

Debugging J2EE Technology apps on JRun and Eclipse

I'm currently using Eclipse 3.1.1 on Adobe (formerly Macromedia) JRun 4.0 for a database-intensive project update. In order to debug some complex Java class business logic, I wanted to run the JRun app inside Eclipse's debugger. Here's how you can set it up in a similar way:

1. Choose the project in Eclipse that contains the class files to debug
2. Make sure that the jrun.jar file is on your project's classpath
3. Choose Run -> Run...
4. Click the Java Application configuration, then the New button.
5. In the main class, enter "jrunx.kernel.JRun".
6. In the Arguments tab, enter "-start ", so for a jrun server named "default" you'd enter "-start default".
7. Enter any JVM arguments you have in Jrun's jvm.config file into the VM arguments field: "-Xms32m -Xmx128m -Dsun.io.useCanonCaches=false".

You can then set breakpoints in your Java classes, and run JRun in Debug mode from within Eclipse during development.

One downside is that you can't debug JSP pages, only Java classes that you use. This application is a Flash Rich Internet Application that uses Flash Remoting to access a J2EE middleware backend, so I don't have to debug JSP for this one. I may review alternative debug methods that include JSP debugging later.

Doug Smith, Senior Developer, Barefoot

Flash & SEO, A Home Run for Barefoot, Part 1

Barefoot recently completed Flash site for Pitch In For Baseball, a non-profit organization dedicated to providing baseball equipment to communities around the world who couldn't afford to purchase it otherwise.

We created a site that targeted Flash 8 so we could take advantage of great new features like high quality font rendering and improved transition effects. The client also wanted the ability to update content about current news, projects, and donor recognition. So, we stored all of the content in a MySQL database using a custom J2EE based content manager deployed on Apache Tomcat.

One of the typical drawbacks developers face when creating an all-Flash site is the issue of Search Engine Optimization, or SEO. Most search engines just ignore .swf files altogether. While Google does index .swf files, the results are very poor because they don't link into a specific navigation point with an all-Flash site.

For example, a Flash site may have a FAQ page with the word "FAQ" on it. Within the Flash, the user clicks the FAQ button and is able to see the FAQ content. However, if a user finds the FAQ content in a search engine that indexed the .swf itself, the link from the search engine to the site will likely take the user to the home page, or directly to the .swf file outside of its HTML container. Either way, the user doesn't see the FAQ content from the search engine, even if that content can be found.

Most solutions to this problem involve creating a completely separate HTML site. The HTML is indexed by search engines, and the content can be found. However, this typically requires developers or clients to maintain completely separate content bases, and prevents users who find the content via search engines from seeing the content in its Flash-enabled glory.

For Pitch In For Baseball, we used a very innovative combination of technology strategies to support search engine links that when clicked, tell the Flash application to go to the page found by the searcher. I'll detail the high-level strategy here, and write upcoming articles to show the details of each phase.

The major components of the strategy are:
  1. Store the content in a database. This provides one place for everyone to update the content, while allowing developers to render that content in multiple ways.

  2. Read the content dynamically into a Flash HTML field.

  3. Code the Flash app so that it can read URLs in order to open sub-content areas. Here are a couple example links:

    http://www.pitchinforbaseball.org/pifbweb/ui/our_dugout/game_plan/
    http://www.pitchinforbaseball.org/pifbweb/ui/where_we_help/faq/

  4. Use SWFObject to embed the Flash app on the page.

  5. Populate the SWFObject <div> block with the same dynamic content that is read into each Flash page. If the user doesn't have Flash 6 or higher, or doesn't have Javascript turned on, they will see this content. Since search engines fall into this category, they index this content. Try out the links in the previous point with JavaScript turned off, and you'll see the flat content.

  6. Dynamically change the links within the content so that they navigate correctly whether inside the Flash, or on Flash HTML.

The result of this design is that the site is completely indexed correctly by Google. Check out this search to see how well it is indexed, and how the Flash automatically goes to the right page.

More details to come!

by Doug Smith, Senior Developer, Barefoot

Installing Ruby on Rails with mod_fcgi for Apache 2

After a few hours of trial and error using advice from many different sites/posts, this is the process that I found successful in getting Ruby on Rails working with the Apache 2 fcgi module on linux. I hope this helps someone hang onto a few more hair follicles.

Before we begin, I can say that this was only successful when I did the setup in this order. Perhaps others have done it in a different way, but this worked for me. BTW, we're using Redhat Enterprise 3.

First, we'll install ruby.

curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.4.tar.gz
tar xvfz ruby-1.8.4.tar.gz
cd ruby-1.8.4
./configure --prefix=/usr/local
make
make install
cd ..


Just to make sure everything installed properly try this:

ruby --version

It should return something like this:

ruby 1.8.4 (2005-12-24) [i686-linux]

Now let's install ruby gems.

curl -O http://rubyforge.org/frs/download.php/5207/rubygems-0.8.11.tgz
tar xvfz rubygems-0.8.11.tgz
cd rubygems-0.8.11
ruby setup.rb
cd ..


Now we need to install the FastCGI development kit.

curl -O http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
tar xvfz fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure --prefix=/usr/local
make
make install
cd ..


Allrighty then. We're moving now.

Install the bindings between Ruby and FastCGI

curl -O http://sugi.nemui.org/pub/ruby/fcgi/ruby-fcgi-0.8.6.tar.gz
tar xvfz ruby-fcgi-0.8.6.tar.gz
cd ruby-fcgi-0.8.6
ruby install.rb config
ruby install.rb setup
ruby install.rb install
cd ..


Next, install the mod_fcgi Apache 2 module.

curl -O http://fastcgi.coremail.cn/mod_fcgid.1.09.tar.gz
tar xvfz mod_fcgid.1.09.tar.gz
cd mod_fcgid.1.09


Check the Makefile to make sure top_dir points to the right directory. Edit if it doesn't.

make
make install
cd ..


It's finally time to install Rails.

gem install rails --include-dependencies

This will take a few minutes. Grab a refreshing beverage. If you really want to be entertained while improving your ruby skills, read why's (poignant) guide to ruby.

Time to get back to work. Before we go nuts trying to see if Rails and Apache are on speaking terms, let's make sure Rails' built in server, WEBrick works. We'll make a quick dummy application to try it out.

rails dummyapp
cd dummyapp
ruby script/server


You should see output similar to this:

=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2006-05-03 11:56:50] INFO WEBrick 1.3.1
[2006-05-03 11:56:50] INFO ruby 1.8.4 (2005-12-24) [i686-linux]
[2006-05-03 11:56:50] INFO WEBrick::HTTPServer#start: pid=8747 port=3000


Now, let's see what the application shows us. I usually do this in a new terminal window.

lynx http://localhost:3000

Hopefully, you can see a page that has "Welcome aboard, You're riding the Rails!" on it, along with links to documentation and other goodies. If you're not, begin abusing hair follicles. Assuming you did see it, quit out of lynx, then shutdown WEBrick in the other terminal by hitting ctrl-c on your keyboard.

Rails and Apache. Joanie and Chachi. Nick and Jessica. Peas and Carrots.

Let's make a super couple. To test Rails and Apache, we need to enter the appropriate lines into our Apache configuration file. I was doing this as an additional virtual host, so mine looks like so:


<VirtualHost 10.10.10.10:80>
ServerAdmin me@gmail.com
ServerName website.com
UseCanonicalName Off

# Set to development, test, or production
DefaultInitEnv RAILS_ENV production
# set to the "public" directory of your app
DocumentRoot /root/dummyapp/public

<Directory "/root/dummyapp/public">
RewriteEngine On
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
Options Indexes ExecCGI FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
AddHandler fcgid-script .fcgi
</Directory>
</VirtualHost>


Now that you've added the block to your Apache config, restart Apache and browse to you site. You should once again see the familiar "Welcome aboard, You're riding the Rails!"

And there was much rejoicing.

Sean Brown, Partner, Technology at Barefoot

Labels: , ,

Flash ExpressInstall Challenge

We have standardized on using the SWFObject method of embedding Flash applications onto web pages. It has a whole host of advantages -- most recently it has proven to overcome the new IE "Activate an ActiveX Control" issue, where users must click to activate any ActiveX control that is embedded with an applet, embed, or object tag.

SWFObject also interfaces with Adobe's ExpressInstall feature very nicely. You can embed ExpressInstall code into a Flash app and if the user doesn't have the required version of Flash (but they have at least Flash v6.0.65), the user can automatically update the Flash plugin.

I ran into a challenge while adding the ExpressInstall to a recent app. I was publishing a .swf as a Flash 8 file, with a text message that appeared if the user didn't have Flash 8 that explained the ExpressInstall process. The problem was that when I tested on Flash Player 6 or 7, the text message was invisible. I even tested using the so_tester file provided with (previously named) FlashObject, and when published as Flash 8, the upgrade message and button were also invisible.

Fortunately, the latest version of SWFObject (1.4) alerts us to the solution I discovered before its release: you must use Device Fonts for any text that could be displayed by a Flash Player < version 8, if you are publishing to Flash 8. Once I changed my text message to using Device Fonts, I could see the text in Flash Player 6 or 7 and all was well.

Doug Smith, Senior Developer at Barefoot.

Add properties to already existing Classes in Flash

This is a simple way to store a property in the Sound Class of Flash for use in the onSoundComplete method (or any built-in method with any built-in class). The theory is called casting:


var my_sound: Object = new Sound();
my_sound.id = this.id;
my_sound.attachSound("someSound");
my_sound.start();
my_sound.onSoundComplete = function()
{
// stop the animation
_root["person" + id].stop();
}


Notice the declaration of Object, in the first line. Should my_sound be defined as Sound, the second line would fail because id is not a predefined property of the Sound class. By declaring my_sound as a generic Object, adding properties is allowed. All Sound properties and methods are still available even with the generic Object definition, hence the use of the onSoundComplete method on line 5. Notice the use of the id property to dynamically define an object on the _root.

More can be read about casting in Flash in Colin Moock's latest book from O'Reilly called "Essential Actionscript 2.0."

Michael Krisher, Senior Developer at Barefoot.

Public Key SSH Authentication

This implementation will give you "passwordless SSH authentication." This can be set up between two machines on which you already have an SSH account. This example uses DSA encryption, but it works the same for RSA.

On the local machine (i.e., your laptop):

ssh-keygen -t dsa

You'll get three prompts. To all three, simply hit enter.

Enter file in which to save the key(/home/youraccount/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:


This creates two files in your local home directory's .ssh folder, id_dsa and id_dsa.pub. id_dsa is your private key file. Guard it closely. id_dsa.pub is your public key file; you'll use this in a moment.

Change into the .ssh folder in your home directory. For me, that meant

cd /home/sbrown/.ssh

Still on your local machine, we want to put a copy your id_dsa.pub file onto your server. I am using secure copy to do it, but you can substitute FTP if you like:

scp id_dsa.pub remote_user@remote_server.com:id_dsa.pub

Obviously, substitute your actual username and machine name into the code above. Now ssh into your account on the remote machine.

Now we're on your remote machine (in remote_user's home directory).

A copy of your local machine's id_dsa.pub file should be in your home directory. We need to copy its contents into a file called authorized_keys in the .ssh directory on your remote account. This assumes the .ssh folder already exists. If not create it first (mkdir .ssh).

cat id_dsa.pub >> .ssh/authorized_keys

Now, set the permissions on your files and folders properly:

chmod 700 .ssh
chmod 600 .ssh/authorized_keys


And don't forget to remove the copy of id_dsa.pub in your home directory.

rm id_dsa.pub

And that's it. Log out of your remote machine, then back on your local machine, ssh back into your remote machine and you should get in with no password.

Sean Brown, Partner, Technology at Barefoot

SQL to find missing linked records

I'm working on a database project that has two tables. One table contains document information, with one record per document. Another table contains parties, the people/companies linked to the documents. There can be many parties for each document. There are two kinds of parties -- party 1 and party 2.

I needed to find all of the documents of a certain type that didn't have any party 1's. To start, I created SQL like this:


SELECT d.document_id
FROM documents d
LEFT OUTER JOIN parties p
  on d.document_id = p.document_id
WHERE p.party_id is null;


This query simply returns all of the document IDs where there is no party linked to each document. This only gets me 1/2 way to my goal, however, because I only want to see the documents that have no linked party 1's. This returns documents that have any parties linked to them, whether party 1 or 2.

To find only those that are missing party 1's, I used the following SQL:


SELECT d.document_id
FROM documents d
LEFT OUTER JOIN parties p
  on d.document_id = p.document_id AND p.party_num = 1
WHERE p.party_id is null


The interesting thing here is that I added conditions you'd normally think to put in the WHERE clause to the condition of the LEFT OUTER JOIN clause. By doing this, the database only tries to link records between the two tables from the type of party I'm looking for -- party_num = 1.

Doug Smith, Senior Developer at Barefoot.