<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Brock&#039;s Software Engineering Blog</title>
	<atom:link href="http://blog.brockbouchard.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.brockbouchard.net</link>
	<description>Thoughts, rants, and lessons learned the hard way.</description>
	<lastBuildDate>Sun, 06 Sep 2009 05:38:47 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='blog.brockbouchard.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/6874388e4b7c56707b6567d86d3e0da1?s=96&#038;d=http://s2.wp.com/i/buttonw-com.png</url>
		<title>Brock&#039;s Software Engineering Blog</title>
		<link>http://blog.brockbouchard.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.brockbouchard.net/osd.xml" title="Brock&#039;s Software Engineering Blog" />
	<atom:link rel='hub' href='http://blog.brockbouchard.net/?pushpress=hub'/>
		<item>
		<title>OH.  MY. GOD!</title>
		<link>http://blog.brockbouchard.net/2009/09/06/oh-my-god/</link>
		<comments>http://blog.brockbouchard.net/2009/09/06/oh-my-god/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 05:38:47 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=91</guid>
		<description><![CDATA[http://www.mono-project.com/MonoTouch
It looks like the Mono project (which is an alternate implementation of .NET) has been ported to the iPhone.
C# and iPhone together at last.  Brilliant!
Posted in Uncategorized       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=91&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>http://www.mono-project.com/MonoTouch</p>
<p>It looks like the Mono project (which is an alternate implementation of .NET) has been ported to the iPhone.</p>
<p>C# and iPhone together at last.  Brilliant!</p>
<br />Posted in Uncategorized  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=91&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/09/06/oh-my-god/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>All the Cool Kids are Using Git</title>
		<link>http://blog.brockbouchard.net/2009/08/11/all-the-cool-kids-are-using-git/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/all-the-cool-kids-are-using-git/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 09:28:34 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Logos of Monsters Eating Trees]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=88</guid>
		<description><![CDATA[So I am a long time user and avid fan of Subversion.  I did a lot of Rails development in 2007, not too much in 2008, then jumped back into things again this year.  In my time away from Rails it seems everyone has switched to using Git!  Most notably the Rails team itself has switched.
This [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=88&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>So I am a long time user and avid fan of <a href="http://subversion.tigris.org/">Subversion</a>.  I did a lot of Rails development in 2007, not too much in 2008, then jumped back into things again this year.  In my time away from Rails it seems everyone has switched to using <a href="http://git-scm.com/">Git</a>!  Most notably the Rails team itself has switched.</p>
<p>This brings up the following random thoughts and/or conerns:</p>
<ol>
<li>Is Git really better?  It looks like it may be.  While it has obvious advantages for a distributed team, it would seem the support for commits while disconnected has advantages even for single-developer projects.  Why just the other day I wanted to commit some changes on one of my projects when I found my Internet down.  Git would have come in handy.</li>
<li>Although Subversion works great for me, should I change for change&#8217;s sake?  To learn a new technology and avoid becoming that guy still clinging to Subversion 4o years from now?</li>
<li>The header image on Git&#8217;s home page has an orange monster eating trees.  Subversion&#8217;s home page does not.  Game/set/match Git.  Subversion better come up with an equally cool monster doing some equally cool or I may be forced to switch.</li>
</ol>
<br />Posted in Uncategorized Tagged: Git, Logos of Monsters Eating Trees, Ruby on Rails, Subversion <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/88/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/88/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/88/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/88/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/88/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=88&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/all-the-cool-kids-are-using-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>TextMate Rocks</title>
		<link>http://blog.brockbouchard.net/2009/08/11/textmate-rocks/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/textmate-rocks/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 09:15:04 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[TextMate]]></category>
		<category><![CDATA[W3C]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=86</guid>
		<description><![CDATA[If you are running Mac OS X and doing any kind of development (Ruby, Rails, HTML, CSS, Javascript, C++, whatever) I highly recommend looking into getting TextMate.  A friend of mine bought a license as a birthday present for me some number of years ago and I had only used it sporadically.  As of late though [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=86&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>If you are running Mac OS X and doing any kind of development (Ruby, Rails, HTML, CSS, Javascript, C++, whatever) I highly recommend looking into getting <a href="http://macromates.com/">TextMate</a>.  A friend of mine bought a license as a birthday present for me some number of years ago and I had only used it sporadically.  As of late though I have started using it for <em>everything</em>!  It is truly fantastic and worth whatever they charge you for it.</p>
<p>My favorite feature?  Built in CSS/HTML W3C validation.  You would be surprised how many of your CSS bugs that you are quick to blame on browser deficiencies are actually a result of your invalid CSS :/</p>
<br />Posted in Uncategorized Tagged: CSS, HTML, Javascript, Ruby, Ruby on Rails, TextMate, W3C <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/86/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/86/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/86/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/86/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/86/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=86&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/textmate-rocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>Rails, Sitemaps, and Google Webmaster Tools</title>
		<link>http://blog.brockbouchard.net/2009/08/11/rails-sitemaps-and-google-webmaster-tools/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/rails-sitemaps-and-google-webmaster-tools/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 08:58:41 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[SEO]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=80</guid>
		<description><![CDATA[I have heard many good things about Google Webmaster Tools, and set out to get brockbouchard.net registered.  One of the best features of the webmaster tools is that you can build a &#8220;Sitemap&#8221; for your site (which is just XML describing your site&#8217;s content) and submit it directly to Google.  However, generating the Sitemap at [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=80&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>I have heard many good things about <a href="http://www.google.com/webmasters/tools">Google Webmaster Tools</a>, and set out to get <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> registered.  One of the best features of the webmaster tools is that you can build a &#8220;Sitemap&#8221; for your site (which is just XML describing your site&#8217;s content) and submit it directly to Google.  However, generating the Sitemap at first looks like an arduous task.  Fortunately, some individuals in the Rails community set out to make the task easier for all of us:</p>
<ol>
<li><a href="http://scoop.cheerfactory.co.uk/2008/02/26/google-sitemap-generator/">Alastair Brunton</a>, with improvements from <a href="http://harrylove.org/2008/06/10/google-sitemaps-with-ruby-on-rails-capistrano-and-cron.html">Harry Love</a>, created a means of generating your Sitemap dynamically for each model in your database.</li>
<li><a href="http://www.webficient.com/2008/09/06/google-sitemap-ruby-on-rails">Phil Misiowiec at Webficient</a> created a tool to generate a Sitemap for your Rails app&#8217;s static content.</li>
</ol>
<p>While each is incredibly useful, I wanted a solution that combined both.  I thus took the code created by all of the above, and extended their solutions to generate a Sitemap for both your dynamic and static content all at once.  Curiously, I also ran into and fixed a problem with the dynamic Sitemap generator whereby the XML created was a single line and Google was rejecting it with a non-descript error.</p>
<p>To get up and running with all of this, do the following:</p>
<p><strong>1. Make sure you have the &#8220;mechanize&#8221; gem installed:</strong></p>
<pre class="brush: bash;">
sudo gem install mechanize
</pre>
<p><strong>2. Be sure to create a &#8220;sitemaps&#8221; subfolder in your [rails_app]/public directory.</strong></p>
<p><strong>3. Copy the two files below to your [rails_app]/lib directory:</strong></p>
<pre class="brush: ruby;">
# static_crawler.rb

require 'mechanize'

class StaticCrawler

  # EXTENSIONS_IGNORED = %w[.csv .doc .docx .gif .jpg .jpeg .js .mp3 .mp4 .mpg .mpeg .pdf .png .ppt .rss .swf .txt .xls .xlsx .xml]
  # BRB - In my case, I want to index document types like doc and pdf
  EXTENSIONS_IGNORED = %w[.csv .gif .jpg .jpeg .js .mp3 .mp4 .mpg .mpeg .png .rss .swf .xml]

  PROTOCOLS_IGNORED = %w[feed ftp itms javascript mailto]

  def initialize(starting_url, credentials = nil, quiet_mode = false, sitemap = false, debug = false)
    @bad_pages = []
    @agent = WWW::Mechanize.new
    @sitemap = sitemap
    @debug = debug
    @visited_pages = []

    if credentials
      creds = credentials.split(':')
      @agent.basic_auth(creds[0], creds[1])
    end

    @quiet_mode = quiet_mode
    @starting_url = starting_url
    @starting_url_domain = starting_url[/([a-z0-9-]+)\.([a-z.]+)/i]
    puts &quot;domain: #{@starting_url_domain}&quot; if @debug
    extract_and_call_urls(starting_url)
    generate_sitemap if @sitemap
  end

  def extract_and_call_urls(url)
    #get page
    puts &quot;#{@visited_pages.size+1} #{url}&quot; unless @quiet_mode
    begin
      page = @agent.get(url)
    rescue =&gt; exception
      @bad_pages &lt;&lt; url
      puts &quot;error: #{url}, #{exception.message}&quot;
      return
    end

    #for any content types we may have missed above, exit if content type is not html
    return if page.instance_of?(WWW::Mechanize::File) || page.content_type.index('text/html') == nil

    #add to array
    @visited_pages &lt;&lt; url

    #get links found on page
    links = page.links

    #for each link, call the url if not in history
    links.each{ |link| extract_and_call_urls(link.href) unless
      ignore_url?(link.href) || @visited_pages.include?(link.href) }
  end

  private

  def ignore_url?(url)
    begin
      return ignored = true if url.nil? ||
                       (url.include? 'http' and !url.include?(&quot;webficient.com&quot;)) ||
                       @bad_pages.include?(url) ||
                       PROTOCOLS_IGNORED.find{ |prt| url =~ /#{prt}:/ } != nil ||
                       EXTENSIONS_IGNORED.find{ |ext| url =~ /#{ext}$/ } != nil
    ensure
      puts &quot;ignored: #{url}&quot; if ignored and @debug
    end
  end

  def generate_sitemap
  	xml_str = &quot;&quot;
  	xml = Builder::XmlMarkup.new(:target =&gt; xml_str, :indent =&gt; 2)

  	xml.instruct!
  	xml.urlset(:xmlns=&gt;'http://www.sitemaps.org/schemas/sitemap/0.9') {
  		@visited_pages.each do |url|
  		  unless @starting_url == url
    	    xml.url {
      	    xml.loc(@starting_url + url)
      			xml.lastmod(Time.now.utc.strftime(&quot;%Y-%m-%dT%H:%M:%S+00:00&quot;))
      			xml.changefreq('weekly')
   			  }
   			end
  		end
  	}

  	save_file(xml_str)

  	# BRB - don't need to call this as something similar is called at the end of ModelCrawler
  	# update_google
  end

	# Saves the xml file to disc. This could also be used to ping the webmaster tools
	def save_file(xml)
		File.open(RAILS_ROOT + '/public/sitemaps/static.xml', &quot;w+&quot;) do |f|
			f.write(xml)
		end
	end

	# Notify google of the new sitemap
	# def update_google
	#     sitemap_uri = @starting_url + '/sitemap.xml'
	#     escaped_sitemap_uri = URI.escape(sitemap_uri)
	#     Net::HTTP.get('www.google.com',
	#                   '/webmasters/tools/ping?sitemap=' +
	#                   escaped_sitemap_uri)
	# end

end
</pre>
<pre class="brush: ruby;">
# model_crawler.rb

require 'net/http'
require 'uri'
require 'zlib'

# A class specific to the application which generates a google sitemap from the contents of the database.
# Author: Alastair Brunton
# Modified: Harry Love 2008-06-09
class ModelCrawler

  def initialize(base_url, sources)
    @base_url = base_url
    @sources = sources
  end

  # 1. Iterate through each model's #get_paths method
  # 2. Create sitemap file for each model
  # 3. Create sitemap index file
  # 4. Ping Google
  def generate
    path_ar = []
    sitemaps = []
    @sources.each do |source|
      # initialize the class and call the get_paths method on it.
      path_ar = eval(&quot;#{source}.get_paths&quot;)
      xml = generate_sitemap(path_ar)
      save_file(source, xml)
    end
    index = generate_sitemap_index(@sources)
    save_file('index', index)
    update_google
  end

  # Create a sitemap document for a model
  def generate_sitemap(path_ar)
    xml_str = &quot;&quot;
    xml = Builder::XmlMarkup.new(:target =&gt; xml_str)
    xml.instruct!
    xml.urlset(:xmlns =&gt; 'http://www.sitemaps.org/schemas/sitemap/0.9') {
      path_ar.each do |path|
        xml.url {
      	  xml.loc(@base_url + path[:url])
      	  xml.lastmod(path[:last_mod])
      	  xml.changefreq('weekly')
        }
      end
    }
    xml_str
  end

  # Create a sitemap index document
  def generate_sitemap_index(sitemaps)
    xml_str = &quot;&quot;
    xml = Builder::XmlMarkup.new(:target =&gt; xml_str, :indent =&gt; 2)
    xml.instruct!
    xml.sitemapindex(:xmlns =&gt; 'http://www.sitemaps.org/schemas/sitemap/0.9') {
      xml.sitemap {
    	  xml.loc(@base_url + &quot;/sitemaps/static.xml&quot;)
    	  xml.lastmod(Time.now.strftime('%Y-%m-%d'))
 	    }
      sitemaps.each do |site|
        xml.sitemap {
      	  xml.loc(@base_url + &quot;/sitemaps/#{site}.xml.gz&quot;)
      	  xml.lastmod(Time.now.strftime('%Y-%m-%d'))
   	    }
      end
    }
    xml_str
  end

  # Save the xml file (gzipped) to disk
  def save_file(source, xml)
    File.open(RAILS_ROOT + &quot;/public/sitemaps/#{source}.xml.gz&quot;, 'w+') do |f|
      gz = Zlib::GzipWriter.new(f)
      gz.write xml
      gz.close
    end
  end

  # Notify Google of the new sitemap index file
  def update_google
    sitemap_uri = @base_url + '/sitemaps/index.xml.gz'
    escaped_sitemap_uri = URI.escape(sitemap_uri)
    Net::HTTP.get('www.google.com', '/webmasters/tools/ping?sitemap=' + escaped_sitemap_uri)
  end
end
</pre>
<p><strong>4. Alter deploy.rb</strong></p>
<p>Now you&#8217;ll need an entry in your [rails_app]/config/deploy.rb file to copy your Sitemaps over with each new release:</p>
<pre class="brush: ruby;">
namespace :sitemap do
  desc &quot;Copy the sitemap files after deploy&quot;
  task :copy_sitemap, :roles =&gt; :app, :on_error =&gt; :continue do
    puts &quot;copying Rails sitemap files&quot;
    run &quot;cp #{previous_release}/public/sitemaps/* #{current_release}/public/sitemaps/&quot;
  end
end

after :deploy, 'sitemap:copy_sitemap'
</pre>
<p><strong>5. Create a rake task</strong></p>
<p>Now add a rake task to actually perform the Sitemap generation by creating the [rails_app]/lib/tasks/sitemap.rake file and adding the following code:</p>
<pre class="brush: ruby;">
require 'static_crawler'
require 'model_crawler'

site_url = ENV['URL'] || 'http://localhost:3000'

namespace :sitemap do

  desc 'Crawl the site and create sitemap xml files for both static and dynamic content.  Set CREDS as username:password if you are hitting a password protected site.'

  task(:generate =&gt; :environment) do
    # Generate static sitemap
    sitemap = StaticCrawler.new(site_url, (ENV['CREDS'] if ENV['CREDS']), true, true, false)

    # Generate dynamic sitemaps for each of the models listed in the array
    models = %w( Project )
    sitemap = ModelCrawler.new(site_url, models)
    sitemap.generate
  end

end
</pre>
<p><strong>6. Setup a cron task</strong></p>
<p>Finally, add an entry in your crontab to periodically run the rake task and generate Sitemaps:</p>
<pre class="brush: bash;">
30 9 * * * cd /path/to/rails/app &amp;&amp; /path/to/rake sitemap:generate URL=http://domain.com RAILS_ENV=production
</pre>
<p>Be sure to verify the path to your rake command.  It can be different on some systems.</p>
<br />Posted in Uncategorized Tagged: Google, Ruby on Rails, SEO <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/80/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=80&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/rails-sitemaps-and-google-webmaster-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>Deploying and Maintaing your Rails Application</title>
		<link>http://blog.brockbouchard.net/2009/08/11/deploying-and-maintaing-your-rails-application/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/deploying-and-maintaing-your-rails-application/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 08:11:30 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Capistrano]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Exim4]]></category>
		<category><![CDATA[Maintenance]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[SEO]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=68</guid>
		<description><![CDATA[So you&#8217;ve bought yourself a good book on rails (I recommend Agile Web Development with Rails, Third Edition), and you&#8217;ve finished developing, and writing tests for, your application.  If you&#8217;ve been following Agile development methods, you have even been deploying to your server using something like Capistrano right from the get go.
But now you are [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=68&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>So you&#8217;ve bought yourself a good book on rails (I recommend <a href="http://www.amazon.com/Agile-Web-Development-Rails-Third/dp/1934356166/ref=sr_1_1?ie=UTF8&amp;qid=1249974162&amp;sr=8-1">Agile Web Development with Rails, Third Edition</a>), and you&#8217;ve finished developing, and writing tests for, your application.  If you&#8217;ve been following Agile development methods, you have even been deploying to your server using something like <a href="http://www.capify.org/index.php/Capistrano">Capistrano</a> right from the get go.</p>
<p>But now you are thinking about going live to the world, and suddenly realize there is still so much more to be done!  This is exactly where I found myself recently with the deployment of <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a>.  Below are some of the tasks that are easy to overlook and how to go about completing them.</p>
<p><strong>1. Keeping Log Files Tidy</strong></p>
<p>While you could have your single production.log file fill up indefinitely on your server, it is better to create a rake task that will automatically truncate and create separate files for logs older than X days.  Below is a rake task that I use called &#8220;clean_logs&#8221; that does just this.  Place this code in a ruby file in your [rails_app]/lib/task directory:</p>
<pre class="brush: ruby;">
require 'ftools'

desc &quot;Truncates and backs up log files.  Deletes backup logs older than ENV['CLEAN_LOGS_DAYS_OLD'] days, default is 30.  Set RAILS_ENV on command line to target correct log file.&quot;
task :clean_logs =&gt; :environment do

  days_ago = ENV['CLEAN_LOGS_DAYS_OLD'] || 30

  environment_name = ENV['RAILS_ENV'].downcase
  log_file = &quot;log/#{environment_name}.log&quot;
  log_file_backup = &quot;log/#{environment_name}-#{Date.today.to_s}.log&quot;

  if File.exist?(log_file)
    # move log file
    File.move log_file, log_file_backup, true
    # delete log files older than days_ago
    puts &quot;Deleting log file backups prior to #{Date.today - days_ago}&quot;
    Dir.foreach &quot;log&quot; do |filename|
      if filename =~ /#{environment_name}-\d\d\d\d-\d\d-\d\d/
        backup_date = Date.parse filename.scan(/\d\d\d\d-\d\d-\d\d/)[0]
        File.delete &quot;log/#{filename}&quot; if Date.today - backup_date &gt; days_ago
      end
    end
  else
    puts &quot;#{log_file_name} does not exist.&quot;
  end

end
</pre>
<p>Note here that X defaults to 30, you can change the default to whatever you like, or you can pass in the number of days to keep.  With this rake task in place, add an entry for it to your crontab:</p>
<pre class="brush: bash;">
0 9 * * * cd /path/to/rails/app &amp;&amp; /path/to/rake clean_logs RAILS_ENV=production
</pre>
<p>Notice that the full path to the rake executable is specified.  In my case, it is /usr/bin/rake.  However on some systems it may be different.</p>
<p><strong>2. Backing Up Your Database</strong></p>
<p>Even if you run a small site with a small audience, or don&#8217;t have access to fancy backup drives or tapes, you should employ some kind of database backup.  This is indeed my situation: <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> and its MySQL database all run on one affordable VPS hosting plan.  Nonetheless I run a database backup every night with the following shell script&#8230;</p>
<pre class="brush: bash;">
#!/bin/sh
/usr/bin/mysqldump -h localhost database_name -uusername -ppassword &gt; /path/to/db/backup/directory/`date +%Y%m%d`.sql
/bin/gzip /path/to/db/backup/directory/`date +%Y%m%d`.sql
</pre>
<p>&#8230;that is called from cron with the following entry&#8230;</p>
<pre class="brush: bash;">
0 10 * * * /path/to/db_backup_script
</pre>
<p>Be sure to verify the exact location of your mysqldump and gzip commands.  They could be different on your system.  Indeed I was loathe at first to go through setting this up, but just the other day MySQL decided to corrupt my live database upon server restart.  Fortunately I had a backup ready and waiting!</p>
<p><strong>3. Handling Errors</strong></p>
<p>The first thing to do here is create custom 404, 422 and 500 error pages.  You&#8217;ll notice that your Rails app has an html file corresponding to each error number under the [rails_app]/public directory.  While the pages created by rails may suffice, it would probably be more helpful to create a page with relevant contact information on it!</p>
<p>The next thing to do is install the <a href="http://agilewebdevelopment.com/plugins/exception_notifier">Exception Notifier</a> plugin.  It&#8217;s a pretty straight-forward installation, with the following catch.  If you are using a recent version of Rails (I believe 2.2 or later), you&#8217;ll need to add a new ruby file to your [rails_app]/config/initializers directory where you will initialize the exception notifier plugin:</p>
<pre class="brush: ruby;">
ExceptionNotifier.exception_recipients = %w(errors@yourdomain.com)
ExceptionNotifier.sender_address = %(errors@yourdomain.com)
</pre>
<p>In earlier versions of Rails you could configure ExceptionNotifier right inside of your production.rb configuration file.  But apparently something changed in a recent version of Rails such that doing so no longer works.</p>
<p>Finally, in order to actually get error emails, <em>don&#8217;t forget to configure your mail server</em> as I talk about below!</p>
<p><strong>4. Configure Your Mail Server</strong></p>
<p>Oh wow did I ever get burnt by this.  I spent way too much of my time wondering why emails sent by cron and my Rails app were not arriving.  While your mail server situation may be more complex and may already be setup by an IT department, in my case my app is a one man show running on an affordable VPS hosting plan.  By default my mail server (exim4) was limiting emails to local domains only.  I only discovered this after looking in my /var/log/exim4/mainlog file:</p>
<pre class="brush: bash;">
... Mailing to remote domains not supported ...
</pre>
<p>Once I turned this off everything was fine.  If you are in the same boat as me, refer to your mail server&#8217;s documentation for info on how to disable this behavior.</p>
<p><strong>5. Permissions</strong></p>
<p>Make sure the directory hosting your application is accessible by the user your web server (Apache, nginx, etc) runs as, and make sure new files placed there pick up those permissions.  I host <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> on <a href="http://slicehost.com">Slice Host</a> (which I highly recommend) and they have a great article about setting up Apache permissions.  While it follows the deployment conventions of their tutorials, it is nonetheless useful as one could  easily draw parallels to their particular environment:</p>
<ol>
<li><a href="http://articles.slicehost.com/2007/9/18/apache-virtual-hosts-permissions">http://articles.slicehost.com/2007/9/18/apache-virtual-hosts-permissions</a></li>
</ol>
<p><strong>6. Maintaing Files in /public</strong></p>
<p>You may have files in your [rails_app]/public directory that are not part of your Rails app; these could be files you upload manually or files that others upload.  However if you are using <a href="http://capistrano.org">Capistrano</a> to deploy your Rails app (and you should be), each successive deployment will leave the files in your [rails_app]/public directory that are not under source control in the directory for the previous release!  Fortunately this is easy enough to get around by putting something similar to the following in your [rails_app]/config/deploy.rb file:</p>
<pre class="brush: ruby;">
namespace :deploy do
  task :move_uploaded_files, :on_error =&gt; :continue do
    run &quot;mv #{previous_release}/public/uploaded_files #{current_release}/public&quot;
  end
end

after &quot;deploy:update_code&quot;, &quot;deploy:move_uploaded_files&quot;
</pre>
<p><strong>7. Basic Search Engine Optimization (SEO)</strong></p>
<p>While I am not an expert in this field, I knew I had to do something about this for my site!  I found a number of good tutorials for this with Rails in mind:</p>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:2088px;width:1px;height:1px;">http://www.seoonrails.com/</div>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:2088px;width:1px;height:1px;">http://www.bingocardcreator.com/articles/rails-seo-tips.htm</div>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:2088px;width:1px;height:1px;">http://www.tonyspencer.com/2007/01/26/seo-for-ruby-on-rails/</div>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:2088px;width:1px;height:1px;">http://noobonrails.blogspot.com/2006/09/good-seo-mojo-with-rails.html</div>
<ol>
<li><a href="http://www.seoonrails.com/">http://www.seoonrails.com/<br />
</a></li>
<li><a href="http://www.bingocardcreator.com/articles/rails-seo-tips.htm">http://www.bingocardcreator.com/articles/rails-seo-tips.htm<br />
</a></li>
<li><a href="http://www.tonyspencer.com/2007/01/26/seo-for-ruby-on-rails/">http://www.tonyspencer.com/2007/01/26/seo-for-ruby-on-rails/<br />
</a></li>
<li><a href="http://noobonrails.blogspot.com/2006/09/good-seo-mojo-with-rails.html">http://noobonrails.blogspot.com/2006/09/good-seo-mojo-with-rails.html</a></li>
</ol>
<p>I also set out to get my Rails app setup with a Google sitemap and Google webmaster tools.  This was a little bit more complicated and I will leave it for my next post!</p>
<br />Posted in Uncategorized Tagged: Apache, Capistrano, Deployment, Exim4, Maintenance, Ruby on Rails, SEO <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/68/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=68&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/deploying-and-maintaing-your-rails-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>Making an iPhone Version of your Site with Rails</title>
		<link>http://blog.brockbouchard.net/2009/08/11/making-an-iphone-version-of-your-site-with-rails/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/making-an-iphone-version-of-your-site-with-rails/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 06:51:05 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Safari]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=57</guid>
		<description><![CDATA[Since the iPhone is the greatest thing ever and will one day solve all of the world&#8217;s problems, I figured I should get brockbouchard.net up and running with an optimized site that automatically displays when browsing on an iPhone.  Sure enough, Rails makes this very eay.  Thanks to a great article on slashdotdash.net, I didn&#8217;t [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=57&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>Since the iPhone is the greatest thing ever and will one day solve all of the world&#8217;s problems, I figured I should get <a href="http://brockbouchard.net">brockbouchard.net</a> up and running with an optimized site that automatically displays when browsing on an iPhone.  Sure enough, Rails makes this very eay.  Thanks to a great article on <a href="http://slashdotdash.net">slashdotdash.net</a>, I didn&#8217;t even have to discover for myself how easy this was:</p>
<p><a href="http://www.slashdotdash.net/2007/12/04/iphone-on-rails-creating-an-iphone-optimised-version-of-your-rails-site-using-iui-and-rails-2/">http://www.slashdotdash.net/2007/12/04/iphone-on-rails-creating-an-iphone-optimised-version-of-your-rails-site-using-iui-and-rails-2/</a></p>
<p>I then said to myself that I wanted my site to behave as follows:</p>
<ol>
<li>Occupy the width of the iPhone&#8217;s screen</li>
<li>When the device is rotated, expand the width of the site and have flow content adjust accordingly (and do not zoom in on content)</li>
</ol>
<p>This how the iPhone version of ESPN&#8217;s website behaves, and is something I wanted to mimic.  However, this is where all of the &#8220;easy&#8221; came to a crashing halt.</p>
<p>I googled around, eventually finding a link to Apple&#8217;s official support pages for building iPhone-specific sites:</p>
<ol>
<li><a href="http://developer.apple.com/safari/">http://developer.apple.com/safari/</a></li>
<li><a href="http://developer.apple.com/safari/library/codinghowtos/Mobile/UserExperience/index.html">http://developer.apple.com/safari/library/codinghowtos/Mobile/UserExperience/index.html</a></li>
<li><a href="http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002079-SW1">http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002079-SW1</a></li>
</ol>
<p>While generally helpful, nothing in any of those articles, or the articles immediately linked to those, helped to answer my problem.  With everything I tried, my site would always stay the same absolute width, zooming in on the content when I rotated.  I eventually stumbled upon a reference of all of the viewport settings one can apply to Mobile Safari:</p>
<ol>
<li><a href="http://devworld.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html">http://devworld.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html</a></li>
</ol>
<p>Sure enough the answer is to use the maximum-scale setting and set it to 1.0:</p>
<pre class="brush: xml;">
&lt;meta name=&quot;viewport&quot; content=&quot;maximum-scale = 1.0, user-scalable = no, width = device-width&quot; /&gt;
</pre>
<p>Maybe it was my fault, but I feel like it was way to hard and took way too long to find that piece of information :/</p>
<p>One last thought: I found the iPhone&#8217;s screen to render colors in a much &#8220;darker&#8221; fashion than on my iMac.  Even with the brightness all the way up on the iPhone, and the brightness toned down on the iMac, I still found I had to use a separate set of &#8220;brighter&#8221; colors for the iPhone site to compensate for its screen.  Thus when developing an iPhone site it is important to test it on the actual device itself, and not solely on any of the various simulators out there!</p>
<br />Posted in Uncategorized Tagged: Apple, iPhone, Ruby on Rails, Safari <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/57/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=57&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/making-an-iphone-version-of-your-site-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>Separating Content from Presentation with HTML and CSS</title>
		<link>http://blog.brockbouchard.net/2009/08/11/separating-content-from-presentation-with-html-and-css/</link>
		<comments>http://blog.brockbouchard.net/2009/08/11/separating-content-from-presentation-with-html-and-css/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 06:28:52 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=45</guid>
		<description><![CDATA[With brockbouchard.net I have tried to take separation of presentation and content to an extreme, with the CSS Zen Garden serving as a primary inspiration.  That is to say the HTML generated by my Rails views contains only the content of my pages, with minimal structural markup.  The appearance of the site (colors, layout, fonts, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=45&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>With <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> I have tried to take separation of presentation and content to an extreme, with the <a href="http://www.csszengarden.com/">CSS Zen Garden</a> serving as a primary inspiration.  That is to say the HTML generated by my Rails views contains only the content of my pages, with minimal structural markup.  The appearance of the site (colors, layout, fonts, etc) is controlled entirely by CSS.</p>
<p><strong>What are the benefits of doing this?</strong> There are many:</p>
<ol>
<li>A professional graphic designer can totally retool your site&#8217;s design in a manner limited only by his or her imagination and knowledge of CSS.  Your interaction from a programming perspective with the designer is very little if not zero!</li>
<li>With the focus of your HTML being solely content and structure, it is easier to appreciate and focus on the semantic statement that your markup is making about your content to search engines.  For example, search engines will look for titles to be in &lt;h1&gt;, &lt;h2&gt; and &lt;h3&gt; header tags, and menus to be in a &lt;ul&gt; list.  With CSS you can then go wild as to how an &lt;h1&gt; or &lt;ul&gt; tag is displayed.  Your header for example, could have its text hidden in order to show a background image representing your site&#8217;s header.  And the &lt;ul&gt; containing your site&#8217;s menu can be altered to display horizontally or vertically, and without list item markers.  This is indeed how <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> was designed.</li>
<li>Your site will behave nicely if loaded by a primitive browser that does not support CSS.  Indeed this is a less of a concern with the ever growing use of smartphones with full-featured browsers.  However, there are still many ordinary phones with internet access that feature a limited browsing environment.  A pure-content HTML site will render nicely in this scenario without the need for a special mobile version of the site.</li>
</ol>
<p><strong>How do we go about doing this?</strong> Let&#8217;s look at the basic structure of <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> as an example.  Below is the basic HTML layout of the site, minus some of the actual information I display:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt;

&lt;head&gt;
&lt;title&gt;My Title&lt;/title&gt;
	&lt;link href=&quot;styles.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div id=&quot;container&quot;&gt;
&lt;div id=&quot;header&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;/&quot; title=&quot;My Website&quot;&gt;&lt;span&gt;My Website&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;
&lt;div id=&quot;menu&quot;&gt;
&lt;ul&gt;
	&lt;li id=&quot;Home&quot;&gt;&lt;a href=&quot;/home&quot; title=&quot;Home&quot;&gt;&lt;span&gt;Home&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li id=&quot;Contact&quot;&gt;&lt;a href=&quot;/contact&quot; title=&quot;Contact&quot;&gt;&lt;span&gt;Contact&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li id=&quot;Projects&quot;&gt;&lt;a href=&quot;/projects&quot; title=&quot;Projects&quot;&gt;&lt;span&gt;Projects&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li id=&quot;Blog&quot;&gt;&lt;a href=&quot;/blog&quot; title=&quot;Blog&quot;&gt;&lt;span&gt;Blog&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li id=&quot;Resume&quot;&gt;&lt;a href=&quot;/resume&quot; title=&quot;Resume&quot;&gt;&lt;span&gt;Resume&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;content&quot;&gt;
&lt;h2 class=&quot;pageTitle&quot;&gt;Welcome&lt;/h2&gt;
&lt;div id=&quot;contentForLayout&quot;&gt;
Content goes here&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footer&quot;&gt;
Pick a theme:
&lt;a href=&quot;?theme=theme1&quot; title=&quot;Theme 1&quot;&gt;Theme 1&lt;/a&gt; |
&lt;a href=&quot;?theme=theme2&quot; title=&quot;Theme 2&quot;&gt;Theme 2&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;
</pre>
<p>Some things to notice:</p>
<ol>
<li>The placement of &lt;div&gt; and &lt;span&gt; tags, along with the ids and classes associated with them, are totally arbitrary and up to you as the programmer.  Just because I have a &lt;div&gt; tag named &#8220;footer&#8221; doesn&#8217;t mean that &lt;div&gt; has to appear at the bottom of the page.  You could use CSS to place your &#8220;footer&#8221; anywhere!</li>
<li>Think of the use of &lt;div&gt; and &lt;span&gt; tags as &#8220;hooks&#8221; for finer grained control inside of CSS.  While you don&#8217;t want to go crazy placing &lt;div&gt; and &lt;span&gt; tags everywhere, in some cases you will find it helpful.  In my case, I used &lt;span&gt; tags inside of my &lt;a&gt; tags as I wanted my menu links to appear as images I had designed in Illustrator.  However, I found that with some browsers the only way to make the text of the link totally disappear and give way to the image was to put the text inside of a &lt;span&gt; tag and hide that.  Unfortunately applying &#8220;font-size: 0&#8243; to &lt;a&gt; tags in my CSS was not working on all browsers and platforms!</li>
<li>I put links at the bottom of the page illustrating how the theme could be changed.  In my case, I have my Rails Application controller check to see at the beginning of all requests if a &#8220;theme&#8221; parameter is specified.  If so, the theme name is stored in a session variable (with the session variable defaulting to the default theme name).  Then, in my view where I spit out the &lt;link /&gt; tag for the style sheet, I choose which style sheet to use based on the theme name.</li>
</ol>
<p><strong>How about the CSS?</strong> While I can&#8217;t post all of the CSS here, here are some of the highlights.  If you want to see how I did everything then feel free to go to <a href="http://brockbouchard.net">brockbouchard.net</a>, view the source, then follow the link to my style sheet.</p>
<pre class="brush: css;">
#container
{
	/* this makes the page a fixed width and centers it */
	margin-left: auto;
	margin-right: auto;
	width: 980px;
}

#header
{
	margin: 0px;
	/* this corresponds to the size of the header image */
	width: 980px;
	height: 90px;
	background-image: url(&quot;/images/main/theme1/header.jpg&quot;);
	background-repeat: no-repeat;
}

#header h1
{
	padding: 0px;
	margin: 0px;
	width: 100%;
	height: 100%;
}

#header h1 a
{
	/* these rules make the link inside of the header take up the entire space of the header */
	/* thus this makes the header a clickable link */
	display: block;
	width: 100%;
	height: 100%;
	text-decoration: none;
	border-width: 0px;
	margin: 0px;
	padding: 0px;
}

#header h1 a span
{
	/* hide the text inside of the header link */
	/* doing &quot;font-size: 0&quot; for the &lt;a&gt; does not work across all browsers */
	visibility: hidden;
}

#menu
{
	margin: 0px;
	/* the menu is rendered as all one image */
	/* the size of the menu items defined below defines the clickable area for each menu item */
	background-image: url(&quot;/images/main/theme1/menu.jpg&quot;);
	background-repeat: no-repeat;
	/* this corresponds to the size of the menu image */
	width: 980px;
	height: 45px;
}

#menu ul
{
	/* this corresponds to the size of the menu image */
	width: 980px;
	height: 45px;
	margin: 0px;
	padding: 0px;
	list-style-type: none;
}

/* this is the necessary CSS to turn list items into invisible, clickable areas over the menu image */

#menu ul li
{
	position: relative;
	display: block;
	height: 40px;
	top: 0px;
}

#menu ul li a
{
	display: block;
	width: 100%;
	height: 100%;
	text-decoration: none;
	border-width: 0px;
	margin: 0px;
	padding: 0px;
}

#menu ul li a span
{
	visibility: hidden;
}

#HomeMenuItem
{
	/* something like this would be repeated for each menu item with the appropriate width filled in */
	float: left;
	width: 104px;
}

#HomeMenuItem a:hover
{
	/* change the appearance of the menu item when the user hovers over */
	/* would need to do something similar for each menu item */
	background: transparent url(&quot;/images/main/theme1/home_hover.jpg&quot;) no-repeat scroll top left;
}
</pre>
<br />Posted in Uncategorized Tagged: CSS, HTML <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/45/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=45&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/11/separating-content-from-presentation-with-html-and-css/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>BrockBouchard.net up and running!</title>
		<link>http://blog.brockbouchard.net/2009/08/10/brockbouchard-net-up-and-running/</link>
		<comments>http://blog.brockbouchard.net/2009/08/10/brockbouchard-net-up-and-running/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 04:57:25 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Environment Variable Editor]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=35</guid>
		<description><![CDATA[So I finally got brockbouchard.net up and running in what I consider a mostly finished state!  I think of it as a personal-site/online-portfolio for sharing my software projects with the world.  Arguably the most useful thing is an Environment Variable Editor that I wrote to get around having to use the horrid series of fixed-size [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=35&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>So I finally got <a title="Brock Bouchard .net" href="http://brockbouchard.net">brockbouchard.net</a> up and running in what I consider a mostly finished state!  I think of it as a personal-site/online-portfolio for sharing my software projects with the world.  Arguably the most useful thing is an <a title="Environment Variable Editor" href="http://brockbouchard.net/projects/environment_variable_editor">Environment Variable Editor</a> that I wrote to get around having to use the horrid series of fixed-size dialogs built into Windows.</p>
<p>The site was built using Rails, and I took the opportunity to over-engineer a few features to learn some new tricks.  I also host the site on VPS plan where I had to deploy and configure everything myself.  This was a highly painful, but more importantly highly informative, experience.  I plan on blogging about what I learned building the site over my next several posts.</p>
<br />Posted in Uncategorized Tagged: Environment Variable Editor, Ruby on Rails <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/35/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/35/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/35/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/35/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/35/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/35/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/35/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/35/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/35/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/35/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=35&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/08/10/brockbouchard-net-up-and-running/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>SMS hack could leave &#8220;every&#8221; iPhone vulnerable</title>
		<link>http://blog.brockbouchard.net/2009/07/29/sms-hack-could-leave-every-iphone-vulnerable/</link>
		<comments>http://blog.brockbouchard.net/2009/07/29/sms-hack-could-leave-every-iphone-vulnerable/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 22:30:34 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=23</guid>
		<description><![CDATA[Nice.
UPDATE: Apple posted a patch rather promptly, and thus my iPhone continues to be the greatest thing to ever happen to humanity.
Posted in Uncategorized Tagged: Apple, iPhone      <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=23&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.appleinsider.com/articles/09/07/29/sms_hack_could_leave_every_iphone_vulnerable.html">Nice</a>.</p>
<p>UPDATE: Apple posted a patch rather promptly, and thus my iPhone continues to be the greatest thing to ever happen to humanity.</p>
<br />Posted in Uncategorized Tagged: Apple, iPhone <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/23/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=23&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/07/29/sms-hack-could-leave-every-iphone-vulnerable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
		<item>
		<title>Windows 7 Multi Touch, WPF and .NET 4.0</title>
		<link>http://blog.brockbouchard.net/2009/07/29/windows-7-multi-touch-wpf-and-net-4-0/</link>
		<comments>http://blog.brockbouchard.net/2009/07/29/windows-7-multi-touch-wpf-and-net-4-0/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 11:13:31 +0000</pubDate>
		<dc:creator>Brock</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET 4.0]]></category>
		<category><![CDATA[Multi Touch]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://blog.brockbouchard.net/?p=13</guid>
		<description><![CDATA[I just got super excited for Windows 7!  When Windows 7 was first announced and the list of features included &#8220;Multi Touch&#8221; technology, I was somewhat skeptical given that I wasn&#8217;t sure there would be hardware to support it.  I thus assumed it might just be a start at MT support.  But recently I have [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=13&subd=brocksoft&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<p>I just got super excited for Windows 7!  When Windows 7 was first announced and the list of features included &#8220;Multi Touch&#8221; technology, I was somewhat skeptical given that I wasn&#8217;t sure there would be hardware to support it.  I thus assumed it might just be a start at MT support.  But recently I have been reading up on what&#8217;s new with .NET 4.0, and hidden in the feature list is a Multi Touch API as part of WPF.  I  worked with WPF quite a bit at my last job in Boston, and it is extremely powerful and flexible.  Adding Multi Touch support will only make it more so!</p>
<p>This got me wondering: is Multi Touch hardware starting to emerge in anticipation of Windows 7?  It turns out it is.  Take for example these offerings from <a href="http://www.shopping.hp.com/webapp/shopping/series_can.do;HHOJSID=qCK2KwsQ262RzvPmXmMJX7QzD52kvRLs3SQxhSpwlzyvhrL6r6FZ!-1987329473?storeName=computer_store&amp;landing=desktops&amp;a1=Category&amp;v1=All-in-One%20PCs">HP</a> and <a href="http://www.dell.com/us/en/home/desktops/desktop-studio-one-19/pd.aspx?refid=desktop-studio-one-19&amp;s=dhs&amp;cs=19">Dell</a>.</p>
<p>Thus I ponder the following:</p>
<ol>
<li>Will I be able to buy one of these HP or Dell All-In-Ones and start creating Multi Touch WPF applications out of the box?  Or am I going to need to interface with whacky low-level Windows APIs or vendor-specific SDKs?</li>
<li>Why is Apple and its community of followers totally quiet about the idea of a Multi Touch iMac?  Maybe Apple figures that Multi Touch only works with something you hold in your hand.  I could see my arm getting tired using a Multi Touch All-In-One all of the time.</li>
<li>Multi Touch applications for full-fledged Windows PCs could be the killer selling point and marketing appeal of Windows 7 that no one has seen coming yet.</li>
</ol>
<p>Well I hope this all shakes out the way I want: to buy a Windows 7 All-In-One this fall and start writing Multi Touch applications in pure WPF.</p>
<br />Posted in Uncategorized Tagged: .NET 4.0, Multi Touch, Windows 7, WPF <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brocksoft.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brocksoft.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brocksoft.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brocksoft.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brocksoft.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brocksoft.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brocksoft.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brocksoft.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brocksoft.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brocksoft.wordpress.com/13/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.brockbouchard.net&blog=8780873&post=13&subd=brocksoft&ref=&feed=1" />]]></content:encoded>
			<wfw:commentRss>http://blog.brockbouchard.net/2009/07/29/windows-7-multi-touch-wpf-and-net-4-0/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cc77facc397f4cddd32a314204e9e457?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">brocksoft</media:title>
		</media:content>
	</item>
	</channel>
</rss>