--- a/.hgignore Tue Aug 10 20:58:46 2010 -0400
+++ b/.hgignore Wed Sep 08 20:15:45 2010 -0400
@@ -7,3 +7,4 @@
deploy_tmp/
backups/
*.swp
+*.un~
--- a/DESIGN.mdown Tue Aug 10 20:58:46 2010 -0400
+++ b/DESIGN.mdown Wed Sep 08 20:15:45 2010 -0400
@@ -3,10 +3,11 @@
Images
======
-Full images for posts should be 600 pixels wide (or less).
+Full images for posts should be 580 pixels wide (or less) and a multiple of 25
+pixels tall.
Headers
=======
Blog and project content block should use h2 and lower. h1 elements are
-reserved for the layout.
\ No newline at end of file
+reserved for the layout.
--- a/content/about.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/about.html Wed Sep 08 20:15:45 2010 -0400
@@ -1,88 +1,36 @@
-{% extends "_flatpage.html" %}
-
+{% extends "skeleton/_base.html" %}
{% hyde
title: "About"
%}
-
-{% block article %}
+{% block content %}
+ <img src="/media/images/self.jpg" class="self right" />
-<a href="http://www.flickr.com/photos/sjl7678/2332680141/"
- title="074/365 by Steve Losh, on Flickr">
- <img src="http://farm3.static.flickr.com/2378/2332680141_533362e5db_m.jpg"
- width="173" height="240" alt="074/365"
- class="right"/>
-</a>
-
-I'm **Steve**.
-
-I'm from **[Rochester, NY][rochester]**.
-
+ <div id="leaf-title"><h1>{{ page.title|safe|typogrify }}</h1></div>
+
+ <div id="leaf-content">
+ {% filter typogrify %}
+ {% markdown %}
+I'm **Steve**. I'm from **[Rochester, NY][rochester]**.
I do a lot of different things.
-If you want to get in touch with me, email me at <steve@stevelosh.com> or find
-me on [Twitter][], [Flickr][], [BitBucket][], [GitHub][], [BrightKite][], or
-[DjangoPeople][].
+If you want to get in touch with me you can [email
+me](mailto:steve@stevelosh.com) or find me on [BitBucket][], [GitHub][],
+[Twitter][], [Forrst][], or [Flickr][].
[rochester]: http://rocwiki.org/
[Twitter]: http://twitter.com/stevelosh/
[Flickr]: http://www.flickr.com/photos/sjl7678/
[BitBucket]: http://bitbucket.org/sjl/
[GitHub]: http://github.com/sjl/
-[BrightKite]: http://brightkite.com/people/stevelosh/
-[DjangoPeople]: http://djangopeople.net/stevelosh/
-
-Music
------
-
-I play electric and upright bass. I've played in a metal band in the past, but
-right now my focus is on jazz and blues. I'm taking lessons with a wonderful
-teacher and hope to be skilled enough to play at dances and such in the near
-future.
-
-I DJ at swing and blues dances fairly often. My taste is pretty broad, and
-I'll cater to whatever the floor wants, but I tend to personally enjoy
-slightly down-tempo, small-group music. Let me know if you need a DJ for a
-dance.
-
-Dancing
--------
-
-I've been swing dancing for about seven years. My first love is Lindy Hop; I
-go to classes, workshops and exchanges as often as my schedule and budget will
-allow. I also give lessons; I'm not *the* most skilled dancer but I do have
-teaching experience and I'm relatively cheap.
+[Forrst]: http://forrst.com/people/stevelosh/
-I've also been blues dancing for a couple of years. I'm not great at it yet
-but I'm getting there. I enjoy it even more than Lindy. My favorite aspect of
-dancing in general is connection and blues seems to bring that out more than
-any other dance.
-
-Lately I've also started getting my feet wet in tango. Whether it'll ever
-become as important to me as blues or Lindy remains to be seen.
-
-Photography
-----------
-
-I like photographing people. Other things as well, but especially people.
-They're the most interesting subject to me. I tend to gravitate toward the
-"art" aspects of photography more than the "journalism" aspects, but I can
-appreciate both.
-
-I shoot digital and film (35mm and medium format) depending on my time limits
-and mood. I develop film in my bathroom and print it in a rented darkroom.
-When I print digital I use a lab nearby; I don't have the money for a
-professional printer just yet.
-
-I don't make my living from photography but I do take small jobs.
-
-I post most of what I take on [my Flickr account][Flickr].
Programming
-----------
-I graduated from [Rochester Institute of Technology](http://rit.edu/) with a
-degree in Computer Science.
+I went to [Rochester Institute of Technology](http://rit.edu/) for a degree in
+Computer Science.
I've done a lot of different things in the field so far. Right now the things
that are captivating me are artificial intelligence and clean, simple,
@@ -91,18 +39,62 @@
I find programming beautiful. That might sound strange, but there are aspects
of programming and math that I can't describe any other way.
-You can take a look at my [projects][] to see the major stuff I've worked on,
-or cut to the chase and look at [my BitBucket account][BitBucket].
+You can take a look at my [projects][] to see some of the major stuff I've
+worked on, or cut to the chase and look at [my BitBucket account][BitBucket].
[projects]: /projects/
+Photography
+----------
+
+I like photographing people. Other things as well, but especially people.
+I tend to gravitate toward the "art" aspects of photography more than the
+"journalism" aspects, but I can appreciate both.
+
+I shoot digital and film (35mm and medium format) depending on my time limits
+and mood. I develop film in my bathroom and print it in a rented darkroom.
+When I print digital I use a lab nearby; I don't have the money for a
+professional printer just yet.
+
+I post most of what I take on [my Flickr account][Flickr].
+
+Dancing
+-------
+
+I teach blues dancing here in Rochester as part of [Lady Luck Blues][].
+I starting blues dancing a few years ago and haven't stopped since. My favorite
+aspect of dancing is connection and blues seems to bring that out more than any
+other dance.
+
+I've also been swing dancing for about seven years. My first love is Lindy Hop; I
+go to classes, workshops and exchanges as often as my schedule and budget will
+allow.
+
+Lately I've begun getting my feet wet in tango. Whether it'll ever become as
+important to me as blues or Lindy remains to be seen.
+
+[Lady Luck Blues]: http://ladyluckblues.com/
+
+Music
+-----
+
+I play electric and upright bass. I've played in a metal band in the past, but
+right now my focus is on jazz and blues.
+
+I DJ at swing and blues dances fairly often. My taste is pretty broad, and
+I'll cater to whatever the floor wants, but I tend to personally enjoy
+slightly down-tempo, small-group music. Let me know if you need a DJ for a
+dance.
+
About the Site
-----------
-If you want to know more about the website itself, check out the [project
+If you want to know more about my site you should check out the [project
page](/projects/stevelosh-com/) about the original version and my [blog
post][hyderewrite] about how I rewrote it.
[hyderewrite]: /blog/2010/01/moving-from-django-to-hyde/
-
+ {% endmarkdown %}
+ {% endfilter %}
+ </div>
{% endblock %}
--- a/content/blog/2008/02/microsoft-entourage-applescript-frustration.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2008/02/microsoft-entourage-applescript-frustration.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Entourage + Applescript = Frustration"
snip: "This is ridiculous."
created: 2008-02-21 15:25:45
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -42,4 +42,4 @@
It's painful, but it works. If anyone has a better solution please let me know
so I can rip this monstrosity out of my code and try to forget about it.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2008/04/shooting-girl-jam.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2008/04/shooting-girl-jam.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Shooting Girl Jam"
snip: "I’m finally getting the kind of dancing photos I want."
created: 2008-04-29 18:31:16
- categories: ["photography", "dancing"]
+ flattr: true
%}
@@ -193,11 +193,12 @@
a weekend of solo jazz and Charleston workshops and awesome swing dances.
If you'd like to see the rest of the photos I took this weekend I posted them
-on [Flickr][]. Feel free to comment here or there; advice/questions/comments
-are always appreciated!
+on [Flickr][]. Feel free to comment there or find me on [Twitter][twsl];
+advice/questions/comments are always appreciated!
[Flickr]: http://flickr.com/photos/sjl7678/collections/72157604785390431/
[Stompology]: http://stompology.com/
[Northeast Girl Jam]: http://jojojackson.com/NEGJ/Home.html
+[twsl]: {{links.twsl}}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2008/08/beauty-in-computer-science-recursion.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2008/08/beauty-in-computer-science-recursion.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Beauty in Computer Science"
snip: "Why I love what I do."
created: 2008-08-29 15:30:38
- categories: ["programming"]
+ flattr: true
%}
@@ -79,7 +79,9 @@
See how we did a few things, then referred to the other piece of paper instead
of repeating ourselves? This lets you make small tasks and put them together
to form bigger ones. That's enough of a primer for now; if something's not
-clear please comment and let me know.
+clear please find me on [Twitter][twsl] and let me know.
+
+[twsl]: {{links.twsl}}
What's Recursion?
---------------
@@ -179,4 +181,4 @@
[Pale Blue Dot]: http://en.wikipedia.org/wiki/Pale_Blue_Dot
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2008/08/negative-space-dancing.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2008/08/negative-space-dancing.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Negative Space in Dancing"
snip: "It’s not just for artsy kids."
created: 2008-08-31 15:33:57
- categories: ["dancing"]
+ flattr: true
%}
@@ -101,4 +101,4 @@
[2]: http://flickr.com/photos/jodiseva/2385347094/
[Seascape]: http://www.sugimotohiroshi.com/seascape.html
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2008/08/on-leading.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2008/08/on-leading.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "On Leading"
snip: "Some of my thoughts on leading after five years of doing it."
created: 2008-08-01 15:28:33
- categories: ["dancing"]
+ flattr: true
%}
@@ -88,4 +88,4 @@
The point I'm trying to make is that "leading" a follower is not just leading.
It's paying attention to the follower and leading *her*.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/01/deploying-site-fabric-and-mercurial.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/01/deploying-site-fabric-and-mercurial.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Deploying with Fabric & Mercurial"
snip: "Trimming typing."
created: 2009-01-15 20:51:09
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -212,9 +212,10 @@
My hope is that this will at least give you some ideas about saving yourself
some time. If that helps you create better websites, I'll be happy. Please
-feel free to comment with any questions or thoughts you have!
+feel free to find me on [Twitter][twsl] with any questions or thoughts you have!
[GitHub]: http://github.com/
+[twsl]: {{links.twsl}}
Update
------
@@ -238,7 +239,7 @@
Here's a sample fabfile from one of the projects I'm working on now. There are
no comments, but I think most things should be self-explanitory. If you have
-any questions just post a comment and I'll be glad to answer them.
+any questions just find me on [Twitter][twsl] and I'll be glad to answer them.
from fabric.api import *
@@ -316,4 +317,4 @@
run("cd %s; sed -i -e 's/DEBUG = .*/DEBUG = False/' local_settings.py" % env.remote_app_dir)
restart()
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/01/going-open-source.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/01/going-open-source.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Going Open Source"
snip: "Why I’m making the code to this website public."
created: 2009-01-13 20:08:56
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -136,4 +136,4 @@
[BitBucket]: http://bitbucket.org/
[GitHub]: http://github.com/
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/01/site-redesign.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/01/site-redesign.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Site Redesign"
snip: "Yeah, I know. Again."
created: 2009-01-11 17:58:23
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -45,4 +45,4 @@
[Squarespace]: http://www.squarespace.com/
[project page]: /projects/stevelosh-com
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/02/how-and-why-i-dj.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/02/how-and-why-i-dj.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "How & Why I DJ"
snip: "I like playing music for dancers."
created: 2009-02-06 17:53:44
- categories: ["music", "dancing"]
+ flattr: true
%}
{% block article %}
@@ -191,7 +191,7 @@
I wrote this because I wanted to share how and why I DJ for dancers. If you're
a DJ, I hope I've given you a couple of ideas for new tricks to make your job
-easier. **Let me know what you think in the comments!**
+easier. **Let me know what you think on [Twitter][twsl]!**
If you don't DJ but think you might want to, great! Please don't be scared off
by my absurdly organized workflow — just because it works for me doesn't
@@ -206,7 +206,8 @@
[eMusic]: http://emusic.com/
[Quicksilver]: http://www.blacktree.com/
[Tempo Widget]: http://mac.softpedia.com/get/Dashboard-Widgets/Music/Tempo-Widget.shtml
+[twsl]: {{links.twsl}}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/02/how-i-shoot-dances.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/02/how-i-shoot-dances.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "How I Shoot Dances"
snip: "Slow shutter and flash."
created: 2009-02-09 18:04:36
- categories: ["photography", "dancing"]
+ flattr: true
%}
{% block article %}
@@ -369,4 +369,4 @@
width="500" height="377" alt="GW-0438" />
</a>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/03/candy-colored-terminal.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/03/candy-colored-terminal.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Candy Colored Terminal"
snip: "Better colors for the OS X Terminal."
created: 2009-03-18 18:26:28
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -91,6 +91,8 @@
${D}\n$ '
I hope this helps! If you'd like to share your color schemes or tell me how to
-make the code for my prompt a bit less ugly, please comment!
+make the code for my prompt a bit less ugly, please find me on [Twitter][twsl]!
-{% endblock %}
\ No newline at end of file
+[twsl]: {{links.twsl}}
+
+{% endblock %}
--- a/content/blog/2009/03/mercurial-bash-prompts.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/03/mercurial-bash-prompts.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Mercurial Bash Prompts"
snip: "Always know where you are."
created: 2009-03-17 21:34:55
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -182,4 +182,4 @@
[hg-prompt](http://stevelosh.com/projects/hg-prompt/) that does everything
much more elegantly. **Use that instead!**
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/04/why-people-dont-like-metal.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/04/why-people-dont-like-metal.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Why People Don’t Like Metal"
snip: "It’s probably not what you think."
created: 2009-04-02 22:32:27
- categories: ["music"]
+ flattr: true
%}
{% block article %}
@@ -128,4 +128,4 @@
you look hard enough you can find some amazing music that you might grow to
love and appreciate.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/05/what-i-hate-about-mercurial.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/05/what-i-hate-about-mercurial.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "What I Hate About Mercurial"
snip: "Hg, I love you, but sometimes you bring me down."
created: 2009-05-29 19:51:05
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -230,4 +230,4 @@
I learned, and I'll still take Mercurial despite the small annoyances.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/06/how-to-contribute-to-mercurial.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/06/how-to-contribute-to-mercurial.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "How to Contribute to Mercurial"
snip: "Ten minutes of setup will make it easier."
created: 2009-06-01 20:09:44
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -389,4 +389,4 @@
corrections or additions -- or if anyone has any questions -- I'll be happy to
update the post. I hope it's helpful!
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2009/08/a-guide-to-branching-in-mercurial.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/08/a-guide-to-branching-in-mercurial.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "A Guide to Branching in Mercurial"
snip: "With illustrations and comparisons to git."
created: 2009-08-30 20:27:12
- categories: ["programming"]
+ flattr: true
%}
{% block article_class %}with-diagrams{% endblock %}
--- a/content/blog/2009/11/my-sitesprint-project-lindyhub.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2009/11/my-sitesprint-project-lindyhub.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "My SiteSprint Project: LindyHub"
snip: "I want to make something awesome for dancers."
created: 2009-11-16 19:15:07
- categories: ["programming", "dancing"]
+ flattr: true
%}
{% block article %}
@@ -48,11 +48,12 @@
Dancers from far and wide will travel to these events to meet and dance with
new people (and old friends).
-If you want more background on dancing post a comment and I'll gladly explain
-more, but this in-a-nutshell explanation should be enough for you to
-understand the rest of this entry.
+If you want more background on dancing find me on [Twitter][twsl] and I'll
+gladly explain more, but this in-a-nutshell explanation should be enough for
+you to understand the rest of this entry.
[Lindy Hop]: http://en.wikipedia.org/wiki/Lindy_hop
+[twsl]: {{links.twsl}}
The Problem
-----------
@@ -222,8 +223,7 @@
It uses [Aardvark Legs][] to keep me sane while writing the CSS, and will use
[jQuery][] for the inline form validation.
-I'm happy to go further in depth if you're curious -- let me know with a
-comment.
+I'm happy to go further in depth if you're curious -- find me on [Twitter][twsl].
[Django]: {{links.django}}
[Python]: {{links.python}}
@@ -239,9 +239,9 @@
another blog entry or two, but I'll try to post updates to
[@lindyhub][twitter] on Twitter much more often.
-If there's anything specific you want to know post a comment here and I'll be
-happy to answer!
+If there's anything specific you want to know find me on [Twitter][twsl] and
+I'll be happy to answer!
[twitter]: http://twitter.com/lindyhub/
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2010/01/moving-from-django-to-hyde.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/01/moving-from-django-to-hyde.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Moving from Django to Hyde"
snip: "Another year, another rewrite."
created: 2010-01-15 20:14:00
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -459,4 +459,4 @@
[bb-repo]: http://bitbucket.org/sjl/stevelosh/
[gh-repo]: http://github.com/sjl/stevelosh/
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2010/01/the-real-difference-between-mercurial-and-git.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/01/the-real-difference-between-mercurial-and-git.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "The Real Difference Between Mercurial and Git"
snip: "It’s not their features."
created: 2010-01-20 21:56:00
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -134,4 +134,4 @@
[record]: http://mercurial.selenic.com/wiki/RecordExtension
[considered]: http://twitter.com/stevelosh/status/7106305374
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2010/02/mercurial-workflows-branch-as-needed.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/02/mercurial-workflows-branch-as-needed.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Mercurial Workflows: Branch As Needed"
snip: "Part 1 of several."
created: 2010-02-28 14:00:00
- categories: ["programming"]
+ flattr: true
%}
{% block article_class %}with-diagrams{% endblock %}
--- a/content/blog/2010/02/my-extravagant-zsh-prompt.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/02/my-extravagant-zsh-prompt.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "My Extravagant Zsh Prompt"
snip: "It’s big, but my monitor isn’t running out of ink."
created: 2010-02-01 01:05:00
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
@@ -21,8 +21,8 @@
**One quick note:** This entry is about the prompt that *I* find useful. You
are not me, so you'll almost certainly have different needs. That's great!
Take this prompt and hack it to make whatever works for you. If you're feeling
-generous you should post a comment explaining what you changed -- I might want
-to steal/appropriate your changes.
+generous you should find me on [Twitter][twsl] and show me what you changed --
+I might want to steal/appropriate your changes.
**Another quick note:** I've customized the colors of my Terminal. They're
based on the [Monokai][] TextMate theme, and I think they look very nice. The
@@ -34,6 +34,7 @@
[tweeted]: http://twitter.com/stevelosh/status/8259755151
[Monokai]: http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/
[candy]: /blog/2009/03/candy-colored-terminal/
+[twsl]: {{links.twsl}}
[TOC]
@@ -59,10 +60,6 @@
(the default on most modern systems) the syntax to create the shell will be
different.
-I'm willing to port the syntax over to bash if there's enough interest. If you
-want me to do that just post a comment and if more than two people want it I
-promise I'll do it.
-
Really, though, you should give Zsh a try.
Screenshots
@@ -197,9 +194,6 @@
To do this I wrote a *very* simple Python script to output my current battery
capacity. The entire script is shown below.
-**Note: this script will *only* work on OS X systems!** If you port it to
-Linux/Windows please post a comment and tell me how you did it!
-
:::python
#!/usr/bin/env python
# coding=UTF-8
@@ -242,8 +236,8 @@
**Note:** The `color_*` variables contain UTF-8 characters which don't show up
in a normal web browser. They *should* be preserved when copying and pasting
-from a decent browser. If the colors don't work post a comment and I'll put
-the raw script up somewhere so you can download it.
+from a decent browser. If the colors don't work find me on [Twitter][twsl] and
+I'll put the raw script up somewhere so you can download it.
**UPDATE:** [ehamberg][] [sent me][ehbtweet] the beginnings of a
Linux-compatible battery capacity script. If you flesh it out and make it into
@@ -259,8 +253,8 @@
brainpower I could spend on making it more efficient could be better spent on
writing or working on something else.
-If you want to improve it, feel free and *please* post a link to your work in
-the comments so I can use it!
+If you want to improve it, feel free and *please* send me the link to your work on
+[Twitter][twsl] so I can use it!
Now that you've got the script, it's time to add it to your prompt.
@@ -486,7 +480,7 @@
it's something that you should take the time to customize into a useful tool.
Feel free to use my prompt as a starting point or just as a source of ideas.
-If you have any questions, suggestions, or examples of your own please post a
-comment -- I'd love to hear them!
+If you have any questions, suggestions, or examples of your own please fine me on
+[Twitter][twsl] -- I'd love to hear them!
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/blog/2010/04/a-faster-feed-apart.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/04/a-faster-feed-apart.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,22 +4,39 @@
title: "A Faster Feed Apart"
snip: "Rethinking A Feed Apart’s backend."
created: 2010-04-30 22:55:00
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
-[An Event Apart][aea] is a conference for web developers and designers that happens a few times a year in various cities. [A Feed Apart][afa] is a site that aggregates tweets during each conference and displays them in a live stream so attendees can follow them during the conference, and people not attending can see what the attendees are talking about.
+[An Event Apart][aea] is a conference for web developers and designers that
+happens a few times a year in various cities. [A Feed Apart][afa] is a site
+that aggregates tweets during each conference and displays them in a live
+stream so attendees can follow them during the conference, and people not
+attending can see what the attendees are talking about.
-A Feed Apart was originally written by [Nick Sergeant][nick] and [Pete Karl][pete] of [Lionburger][lionburger] during one of the conferences. Since then a lot of people have used it and love it.
+A Feed Apart was originally written by [Nick Sergeant][nick] and [Pete
+Karl][pete] of [Lion Burger][lionburger] during one of the conferences. Since
+then a lot of people have used it and love it.
-The current A Feed Apart site is not without its problems. It was written in a single night so it's not perfect. During the last conference it went down several times and lost some tweets along the way.
+The current A Feed Apart site is not without its problems. It was written in
+a single night so it's not perfect. During the last conference it went down
+several times and lost some tweets along the way.
-I work at [Dumbwaiter Design][dwaiter] with Nick and one day he mentioned that it would be cool if we rewrote A Feed Apart from the ground up. He's learned a lot about how people use the site and what the big problems are, so we'd have a better idea of what we need to accomplish.
+I work at [Dumbwaiter Design][dwaiter] with Nick and one day he mentioned that
+it would be cool if we rewrote A Feed Apart from the ground up. He's learned
+a lot about how people use the site and what the big problems are, so we'd have
+a better idea of what we need to accomplish.
-Nick, myself and [Ali Ali][ali] have risen to the challenge and started rewriting A Feed Apart. Ali is a designer and is taking care of the design of the new site. Nick is handling all the frontend HTML, CSS and Javascript. My job is the backend.
+Nick, myself and [Ali Ali][ali] have risen to the challenge and started
+rewriting A Feed Apart. Ali is a designer and is taking care of the design of
+the new site. Nick is handling all the frontend HTML, CSS and Javascript. My
+job is the backend.
-Ali posted a [blog entry][aliblog] about the design of the new version so I figured I'd write about the backend to show how I'm trying to improve it. If you have any advice I'd love to hear it -- the next An Event Apart conference is about three weeks away so there's still time to add improvements.
+Ali posted a [blog entry][aliblog] about the design of the new version so
+I figured I'd write about the backend to show how I'm trying to improve it. If
+you have any advice I'd love to hear it -- the next An Event Apart conference
+is about three weeks away so there's still time to add improvements.
[aea]: http://aneventapart.com/
[afa]: http://afeedapart.com/
@@ -35,7 +52,9 @@
How AFA is Used
---------------
-You can't hope to improve on a site unless you know how people are going to use it. AFA has been around for a while and Nick has learned a lot about what people want to get out of it.
+You can't hope to improve on a site unless you know how people are going to use
+it. AFA has been around for a while and Nick has learned a lot about what
+people want to get out of it.
There are three main kinds of users of AFA:
@@ -45,63 +64,110 @@
### People Attending the Conference
-People that attend AEA are web developers and designers. They're up-to-date on the latest technology and almost all of them use [Twitter][].
+People that attend AEA are web developers and designers. They're up-to-date on
+the latest technology and almost all of them use [Twitter][].
-During the conference you'll see a sea of laptops in the audience. Attendees will tweet about whatever is happening *right now*. There's a huge amount of conversation that happens between attendees that AFA is trying to collect and present.
+During the conference you'll see a sea of laptops in the audience. Attendees
+will tweet about whatever is happening *right now*. There's a huge amount of
+conversation that happens between attendees that AFA is trying to collect and
+present.
-A simple example is one that Nick mentioned to me: if a presenter mentions a website during her presentation someone will tweet the URL so other people can have a link to easily click on. Attendees will also tweet their agreement or disagreement with what the presenter is saying *as they're speaking*.
+A simple example is one that Nick mentioned to me: if a presenter mentions
+a website during her presentation someone will tweet the URL so other people
+can have a link to easily click on. Attendees will also tweet their agreement
+or disagreement with what the presenter is saying *as they're speaking*.
-The most important aspect of AFA for this group of people is the *real time conversation*. If AFA doesn't show tweets until a minute after they've been posted it's useless to these people.
+The most important aspect of AFA for this group of people is the *real time
+conversation*. If AFA doesn't show tweets until a minute after they've been
+posted it's useless to these people.
-Another important part of AFA for attendees is that it's a one-stop-shop for the conversation behind AEA. Switching between windows/tabs/applications to read and contribute is annoying.
+Another important part of AFA for attendees is that it's a one-stop-shop for
+the conversation behind AEA. Switching between windows/tabs/applications to
+read and contribute is annoying.
### People That Wish They Were Attending the Conference
-The next group of users is those that can't attend the conference for a variety of reasons but are still interested in what's going on.
+The next group of users is those that can't attend the conference for a variety
+of reasons but are still interested in what's going on.
-For this group the real time nature of AFA is unimportant. They're probably not going to be following the conversation 24/7 so if a tweet takes a few minutes to display it's not a big deal.
+For this group the real time nature of AFA is unimportant. They're probably
+not going to be following the conversation 24/7 so if a tweet takes a few
+minutes to display it's not a big deal.
-What these people *do* care about is the integrity of the stream. They don't want to miss any part of the conversation. If AFA loses tweets they're better off doing a simple search on Twitter because they'll get the whole story.
+What these people *do* care about is the integrity of the stream. They don't
+want to miss any part of the conversation. If AFA loses tweets they're better
+off doing a simple search on Twitter because they'll get the whole story.
### Speakers and Organizers
The last main group of users is the speakers and organizers of AEA.
-Any speaker worth their salt will want to know what people are said about their presentation. Obviously they can't be reading AFA while they're presenting, but afterword they'll certainly want to go back and see what people were saying during their specific presentation.
+Any speaker worth their salt will want to know what people are said about their
+presentation. Obviously they can't be reading AFA while they're presenting,
+but afterword they'll certainly want to go back and see what people were saying
+during their specific presentation.
-Likewise, organizers want to know which presentations people liked and which ones people didn't enjoy. This could easily influence who they choose to invite to future conferences.
+Likewise, organizers want to know which presentations people liked and which
+ones people didn't enjoy. This could easily influence who they choose to
+invite to future conferences.
-For this group the most important aspect of AFA is the organization of the conversation into chunks, each of which applies to a single presentation. By reading through each chunk of conversation they can get an idea of the general response to each presentation.
+For this group the most important aspect of AFA is the organization of the
+conversation into chunks, each of which applies to a single presentation. By
+reading through each chunk of conversation they can get an idea of the general
+response to each presentation.
[Twitter]: http://twitter.com/
Goals
-----
-Once we identified the main users of AFA we were able to come up with the goals for the new version of the site:
+Once we identified the main users of AFA we were able to come up with the goals
+for the new version of the site:
-* **Stay sane while developing.** Ali, Nick and myself are rewriting the site as a side project, so we don't want it to take *too* much of our time or cause *too* much stress.
+* **Stay sane while developing.** Ali, Nick and myself are rewriting the site
+ as a side project, so we don't want it to take *too* much of our time or cause
+ *too* much stress.
-* **Provide the real time conversation.** The site needs to be fast and responsive, so people at the conferences can use it to converse.
+* **Provide the real time conversation.** The site needs to be fast and
+ responsive, so people at the conferences can use it to converse.
-* **Don't miss anything.** People following along from home shouldn't feel like they're missing anything. We want to provide a *complete* version of the conversation happening behind the event.
+* **Don't miss anything.** People following along from home shouldn't feel
+ like they're missing anything. We want to provide a *complete* version of the
+ conversation happening behind the event.
+
+* **Organize the conversation.** Presenters and speakers need a way to see
+ what people are saying about them. They want to know what people think about
+ each "chunk" of the event.
-* **Organize the conversation.** Presenters and speakers need a way to see what people are saying about them. They want to know what people think about each "chunk" of the event.
-
-* **Grease the wheels of (physical) social interaction.** This is something that AFA hasn't tried to address before, but that we'd like to work on with this version. There are a lot of people at each conference and we'd like to help them get together. Whether it's going out for dinner or meeting up at the [Media Temple][mt] party we want to get people talking to each other. I won't talk about this goal in this post because we're still figuring out the best way to do it.
+* **Grease the wheels of (physical) social interaction.** This is something
+ that AFA hasn't tried to address before, but that we'd like to work on with
+ this version. There are a lot of people at each conference and we'd like to
+ help them get together. Whether it's going out for dinner or meeting up at the
+ [Media Temple][mt] party we want to get people talking to each other. I won't
+ talk about this goal in this post because we're still figuring out the best way
+ to do it.
[mt]: http://mediatemple.net/
Staying Sane
------------
-If the three of us tried to create the site with nothing more than a couple of laptops and a few chats in person we'd go crazy. We use a few tools to help us manage the development of the site.
+If the three of us tried to create the site with nothing more than a couple of
+laptops and a few chats in person we'd go crazy. We use a few tools to help us
+manage the development of the site.
-To create **wireframes of the design** we're using a free account at [Hot Gloo][hotgloo]. Hot Gloo is a great tool that lets us quickly sketch out ideas and comment on them.
+To create **wireframes of the design** we're using a free account at [Hot
+Gloo][hotgloo]. Hot Gloo is a great tool that lets us quickly sketch out ideas
+and comment on them.
-To share **design comps** we're using [Dropbox][]. It's simple to set up a shared Dropbox folder and Nick and I can get real time updates when Ali makes changes to the design.
+To share **design comps** we're using [Dropbox][]. It's simple to set up
+a shared Dropbox folder and Nick and I can get real time updates when Ali makes
+changes to the design.
-To **work together on the code** Nick and I use [Mercurial][] repositories. Mercurial lets us work on the same code bases simultaneously and we almost never have to worry about merging. We use [Codebase][] for hosting and issue tracking.
+To **work together on the code** Nick and I use [Mercurial][] repositories.
+Mercurial lets us work on the same code bases simultaneously and we almost
+never have to worry about merging. We use [Codebase][] for hosting and issue
+tracking.
[hotgloo]: http://hotgloo.com/
[Dropbox]: http://dropbox.com/
@@ -111,34 +177,71 @@
Being Real Time
---------------
-The previous version of AFA wasn't *truly* real time. When you went to the site your browser would ask AFA for the newest updates every 10 seconds.
+The previous version of AFA wasn't *truly* real time. When you went to the
+site your browser would ask AFA for the newest updates every 10 seconds.
+
+There are two main problems with this approach. The first is that it's not
+really *real time*. I've noticed this being an issue in my own experience.
-There are two main problems with this approach. The first is that it's not really *real time*. I've noticed this being an issue in my own experience.
-
-When I watch any of the various "live streams" of [Apple][] press conferences I'm usually at work where other people are also watching. We very rarely load the pages of the streaming sites like Gizmodo at the exact same second, so our browsers will be out of sync with each other. Nick might get an update that I would have to wait 8 more seconds to see.
+When I watch any of the various "live streams" of [Apple][] press conferences
+I'm usually at work where other people are also watching. We very rarely load
+the pages of the streaming sites like Gizmodo at the exact same second, so our
+browsers will be out of sync with each other. Nick might get an update that
+I would have to wait 8 more seconds to see.
-When I glance over at his screen and see an update that I don't have I instinctively refresh the page to get it. This defeats the purpose of the "live updating" code that the developers of these sites worked on. They may as well have just made a static page and told me to refresh.
+When I glance over at his screen and see an update that I don't have
+I instinctively refresh the page to get it. This defeats the purpose of the
+"live updating" code that the developers of these sites worked on. They may as
+well have just made a static page and told me to refresh.
-The second problem is that querying every 10 seconds can be taxing on the site's database. We're doing this as a side project so we don't have unlimited funding for a hefty database server. If 1,000 people are querying for updates every 10 seconds that's 100 requests per second to the database. This means we need to have some kind of in-memory cacheing if we want the site to feel snappy on modest hardware.
+The second problem is that querying every 10 seconds can be taxing on the
+site's database. We're doing this as a side project so we don't have unlimited
+funding for a hefty database server. If 1,000 people are querying for updates
+every 10 seconds that's 100 requests per second to the database. This means we
+need to have some kind of in-memory cacheing if we want the site to feel snappy
+on modest hardware.
-We want the new AFA to be truly real time. To do this we need to use [long polling][longpolling] by users' browsers to wait for updates and return them as soon as they come in. We also need to retrieve the updates as fast as we possibly can, and they need to be stored in memory to avoid hitting the database constantly.
+We want the new AFA to be truly real time. To do this we need to use [long
+polling][longpolling] by users' browsers to wait for updates and return them as
+soon as they come in. We also need to retrieve the updates as fast as we
+possibly can, and they need to be stored in memory to avoid hitting the
+database constantly.
[Apple]: http://apple.com/
[longpolling]: http://en.wikipedia.org/wiki/Push_technology#Long_polling
### Retrieving Updates
-The bulk of the conversation about AEA conferences comes from Twitter. Tweets are the most important items that we need to display on the site, so we're using Twitter's streaming API to pull them in.
+The bulk of the conversation about AEA conferences comes from Twitter. Tweets
+are the most important items that we need to display on the site, so we're
+using Twitter's streaming API to pull them in.
-Since we don't want to tie up an entire server to pull in tweets I've decided to create a [Diesel][]-based application called **The Nozzletron** to parse the streaming API. Diesel is a [Python][] framework that takes an elegant approach to asynchronous communication with clients and servers.
+Since we don't want to tie up an entire server to pull in tweets I've decided
+to create a [Diesel][]-based application called **The Nozzletron** to parse the
+streaming API. Diesel is a [Python][] framework that takes an elegant approach
+to asynchronous communication with clients and servers.
-Twitter's streaming API accepts HTTP requests and returns "chunked" responses, each of which is a tweet. Unfortunately the Diesel's built-in HTTP client doesn't handle chunked HTTP responses so I had to write some code to handle them myself.
+Twitter's streaming API accepts HTTP requests and returns "chunked" responses,
+each of which is a tweet. Unfortunately the Diesel's built-in HTTP client
+doesn't handle chunked HTTP responses so I had to write some code to handle
+them myself.
-The Nozzletron will connect to Twitter's streaming API and wait for data to come in. If there's no data to process it will relinquish the server's processor so it can do other things. Processing a single tweet that comes in doesn't take much time, so the server is free to do other things most of the time.
+The Nozzletron will connect to Twitter's streaming API and wait for data to
+come in. If there's no data to process it will relinquish the server's
+processor so it can do other things. Processing a single tweet that comes in
+doesn't take much time, so the server is free to do other things most of the
+time.
-I've also created another application called **The Flickrtron** to pull in [Flickr][] photos. Unfortunately Flickr doesn't have a streaming API like Twitter so I have to resort to polling Flickr's API every few minutes for new photos. Flickr is much less of a real time medium than Twitter though, so I don't think this is a very big problem.
+I've also created another application called **The Flickrtron** to pull in
+[Flickr][] photos. Unfortunately Flickr doesn't have a streaming API like
+Twitter so I have to resort to polling Flickr's API every few minutes for new
+photos. Flickr is much less of a real time medium than Twitter though, so
+I don't think this is a very big problem.
-I'm using a Python library called [Beej's Flickr API][flickrapi] to talk to Flickr. It is horrible. It calls itself an "API" but is really just a thin wrapper around calls to the Flickr API. The objects it returns for API calls are Elementtree objects representing the XML of the response.
+I'm using a Python library called [Beej's Flickr API][flickrapi] to talk to
+Flickr. It is horrible. It calls itself an "API" but is really just a thin
+wrapper around calls to the Flickr API. The objects it returns for API calls
+are Elementtree objects representing the XML of the response.
I wish I could do something like:
@@ -153,7 +256,8 @@
photo.get('secret'),
)
-I wish there were a better Python Flickr API out there but there doesn't seem to be one. If I've missed it please let me know!
+I wish there were a better Python Flickr API out there but there doesn't seem
+to be one. If I've missed it please let me know!
[Diesel]: http://dieselweb.org/
[Python]: http://python.org/
@@ -162,15 +266,26 @@
### Storing Updates
-We need a fast way to store and retrieve updates so AFA can provide a real time view of the conversation happening at AEA. With this in mind I've chosen [Redis][] to store the updates of the currently-happening event.
+We need a fast way to store and retrieve updates so AFA can provide a real time
+view of the conversation happening at AEA. With this in mind I've chosen
+[Redis][] to store the updates of the currently-happening event.
-Redis is an easy-to-set-up, disgustingly-fast, in-memory data store. It's similar to [memcached][] but has more intelligent data structures that make my life easier for this project.
+Redis is an easy-to-set-up, disgustingly-fast, in-memory data store. It's
+similar to [memcached][] but has more intelligent data structures that make my
+life easier for this project.
-As updates (tweets and flickr photos) are scraped by The Nozzletron and The Flickrtron they're placed at the tail end of a Redis list. That means I can quickly and easily get all the items since item `N` when a user's browser requests them with a single `LRANGE {list-key} N -1` call.
+As updates (tweets and flickr photos) are scraped by The Nozzletron and The
+Flickrtron they're placed at the tail end of a Redis list. That means I can
+quickly and easily get all the items since item `N` when a user's browser
+requests them with a single `LRANGE {list-key} N -1` call.
-I'm also keeping a few other pieces of information in Redis. For example, there's a set of photo IDs held in the `{item-key}:flickrtron:grabbed_photos` key that keeps track of all of the photos we've already seen.
+I'm also keeping a few other pieces of information in Redis. For example,
+there's a set of photo IDs held in the `{item-key}:flickrtron:grabbed_photos`
+key that keeps track of all of the photos we've already seen.
-This makes it easy to tell if we've already seen a photo (and therefore don't need to query Flickr for more information) -- it's a simple `SISMEMBER {item-key}:flickrtron:grabbed_photos {photo-id}` call.
+This makes it easy to tell if we've already seen a photo (and therefore don't
+need to query Flickr for more information) -- it's a simple `SISMEMBER
+{item-key}:flickrtron:grabbed_photos {photo-id}` call.
I'm also using Redis to store statistics about the site like:
@@ -178,32 +293,57 @@
* How many photos we've scraped.
* How many people are currently waiting for updates.
-This kind of information will be extremely valuable in the future when we're planning improvements to the site. Redis makes it fast and safe to update this information using the `INCRBY` and `DECR` commands.
+This kind of information will be extremely valuable in the future when we're
+planning improvements to the site. Redis makes it fast and safe to update this
+information using the `INCRBY` and `DECR` commands.
-There's one more component to The Nozzletron and The Flickrton that I haven't mentioned. Both use Redis' `PUBLISH` command to push new updates out to users' browsers as they arrive. I'll talk more about that in the next section.
+There's one more component to The Nozzletron and The Flickrton that I haven't
+mentioned. Both use Redis' `PUBLISH` command to push new updates out to users'
+browsers as they arrive. I'll talk more about that in the next section.
[Redis]: http://code.google.com/p/redis/
[memcached]: http://memcached.org/
### Sending Updates to Users
-As I mentioned before we want to send updates to users *as soon as they're received*. To do this I've created another Diesel-based application called **Halley** to handle this [Comet][]-style communication.
+As I mentioned before we want to send updates to users *as soon as they're
+received*. To do this I've created another Diesel-based application called
+**Halley** to handle this [Comet][]-style communication.
-Halley has a few components. The first uses Diesel's [Redis API][dieselredis] to subscribe to a Redis channel like `live:{event-id}:items` and [fire][dieselfire] off messages whenever something new comes in. As soon as a new update comes in from The Nozzletron or The Flickrtron all of Halley's clients will get it.
+Halley has a few components. The first uses Diesel's [Redis API][dieselredis]
+to subscribe to a Redis channel like `live:{event-id}:items` and
+[fire][dieselfire] off messages whenever something new comes in. As soon as
+a new update comes in from The Nozzletron or The Flickrtron all of Halley's
+clients will get it.
-When I started working on AFA Diesel's Redis client didn't support the very new `PUBLISH`/`SUBSCRIBE`/`UNSUBSCRIBE` commands. I implemented them, put my changes on [BitBucket][], sent a pull request, and started talking to the Diesel crew on IRC.
+When I started working on AFA Diesel's Redis client didn't support the very new
+`PUBLISH`/`SUBSCRIBE`/`UNSUBSCRIBE` commands. I implemented them, put my
+changes on [BitBucket][], sent a pull request, and started talking to the
+Diesel crew on IRC.
-One of the maintainers pulled my patches and made them even better. Now Diesel's Redis client has full `PUBLISH`/`SUBSCRIBE`/`UNSUBSCRIBE` support. It's a great example of how open source projects can produce awesome results.
+One of the maintainers pulled my patches and made them even better. Now
+Diesel's Redis client has full `PUBLISH`/`SUBSCRIBE`/`UNSUBSCRIBE` support.
+It's a great example of how open source projects can produce awesome results.
-The other main component of Halley is an HTTP server that listens for connections from browsers. The Javascript on the site will call Halley and say "I need updates since number `X`", where `X` is the length of the Redis list of updates at the last time it spoke to the server.
+The other main component of Halley is an HTTP server that listens for
+connections from browsers. The Javascript on the site will call Halley and say
+"I need updates since number `X`", where `X` is the length of the Redis list of
+updates at the last time it spoke to the server.
Halley uses Diesel's [HTTP Server][dieselhttp] to manage these requests.
-If a client is asking for everything since `X` and `X` is a smaller number than the current number of items it will return the updates that have happened since then. This might happen if we return an update and then two more updates happen before the browser gets around to sending another request.
+If a client is asking for everything since `X` and `X` is a smaller number than
+the current number of items it will return the updates that have happened since
+then. This might happen if we return an update and then two more updates
+happen before the browser gets around to sending another request.
-If a client is asking for everything since `X` and `X` is equal to the current number of items Halley will wait for a new message to be fired from the [Loop][dieselloop] that's watching the Redis channel. While Halley waits she relinquishes the processor to the server so other requests can be handled.
+If a client is asking for everything since `X` and `X` is equal to the current
+number of items Halley will wait for a new message to be fired from the
+[Loop][dieselloop] that's watching the Redis channel. While Halley waits she
+relinquishes the processor to the server so other requests can be handled.
-There's a bit of code to prevent DoS attacks that request every item in the queue over and over again, of course.
+There's a bit of code to prevent DoS attacks that request every item in the
+queue over and over again, of course.
[Comet]: http://en.wikipedia.org/wiki/Comet_(programming)
[dieselredis]: http://bitbucket.org/boomplex/diesel/src/tip/diesel/protocols/redis.py
@@ -215,21 +355,38 @@
Organizing the Conversation
---------------------------
-The live stream is an important component of AFA, but it's not the only one. We also need to organize updates into logical chunks by event and presentation, and provide archives of old events so people can see what happened.
-
-The main AFA site is built with [Django][] and served with [Gunicorn][] and [Nginx][]. It uses a [Postgresql][] database to store data that's not "live". Because queries for live data are handled with Diesel and Redis we don't need to send those request through the full Django/Postgresql stack. Django and Postgresql are only involved when you load a fresh page, and they're *more* than capable of handling the amount of traffic that AFA gets for those kind of requests.
+The live stream is an important component of AFA, but it's not the only one.
+We also need to organize updates into logical chunks by event and presentation,
+and provide archives of old events so people can see what happened.
-I've created an application called **The Strainer** to copy data from the live stream to the Postgresql database. The Strainer looks at the list of live items in Redis, parses those items into Django models and saves them to the Postgresql database.
-
-Using two different types of stores (Redis and Postgresql) means we can get the best of both worlds for AFA:
+The main AFA site is built with [Django][] and served with [Gunicorn][] and
+[Nginx][]. It uses a [Postgresql][] database to store data that's not "live".
+Because queries for live data are handled with Diesel and Redis we don't need
+to send those request through the full Django/Postgresql stack. Django and
+Postgresql are only involved when you load a fresh page, and they're *more*
+than capable of handling the amount of traffic that AFA gets for those kind of
+requests.
-* We can keep the live data that's accessed *constantly* in an in-memory Redis datastore which makes it blazingly fast.
+I've created an application called **The Strainer** to copy data from the live
+stream to the Postgresql database. The Strainer looks at the list of live
+items in Redis, parses those items into Django models and saves them to the
+Postgresql database.
-* We can keep the less-frequently-used data in an on-disk Postgresql database which lets us to keep our memory usage low and hosting costs down.
+Using two different types of stores (Redis and Postgresql) means we can get the
+best of both worlds for AFA:
-Django's models and managers make it very easy to separate updates out into the various sessions and presentations that happen at the conferences.
+* We can keep the live data that's accessed *constantly* in an in-memory Redis
+ datastore which makes it blazingly fast.
+
+* We can keep the less-frequently-used data in an on-disk Postgresql database
+ which lets us to keep our memory usage low and hosting costs down.
-Sessions and presentations are much less in-demand than the live stream so we can take advantage of Django's abstractions without worrying about the extra memory/CPU usage we incur by doing so.
+Django's models and managers make it very easy to separate updates out into the
+various sessions and presentations that happen at the conferences.
+
+Sessions and presentations are much less in-demand than the live stream so we
+can take advantage of Django's abstractions without worrying about the extra
+memory/CPU usage we incur by doing so.
[Django]: http://djangoproject.com/
[Gunicorn]: http://gunicorn.org/
@@ -239,20 +396,31 @@
Staying Consistent
------------------
-Another problem AFA has faced in the past is losing tweets. No code is perfect (and mine *certainly* is not) so we need to anticipate that some of the applications we're using will crash at some point.
+Another problem AFA has faced in the past is losing tweets. No code is perfect
+(and mine *certainly* is not) so we need to anticipate that some of the
+applications we're using will crash at some point.
-I'm using [Supervisord][] to monitor the various processes of AFA on the server. If a process crashes for some reason it will be restarted automatically.
+I'm using [Supervisord][] to monitor the various processes of AFA on the
+server. If a process crashes for some reason it will be restarted
+automatically.
-Supervisord also has a wonderful Python API, so I've created a simple Dashboard view in the Django site that lets us stop/start/restart each individual process with a simple web interface. The dashboard also shows us the current memory usage of the server and some other statistics so we can monitor how things are working through a web browser (instead of SSH'ing into the server, which is a pain on a phone).
+Supervisord also has a wonderful Python API, so I've created a simple Dashboard
+view in the Django site that lets us stop/start/restart each individual process
+with a simple web interface. The dashboard also shows us the current memory
+usage of the server and some other statistics so we can monitor how things are
+working through a web browser (instead of SSH'ing into the server, which is
+a pain on a phone).
[Supervisord]: http://supervisord.org/
Getting Bigger
--------------
-An Event Apart is a large event, but it's not a *huge* event. Despite this I've been trying to build the backend in a way that can be easily scaled.
+An Event Apart is a large event, but it's not a *huge* event. Despite this
+I've been trying to build the backend in a way that can be easily scaled.
-Right now it's hosted on a single server, but each of the individual components could be moved to a separate server with less than an hour of work each:
+Right now it's hosted on a single server, but each of the individual components
+could be moved to a separate server with less than an hour of work each:
* Redis
* Postgresql
@@ -262,15 +430,21 @@
* The Strainer
* Halley
-Moving Django/Gunicorn, Nginx, Redis, Halley, and Postgresql to dedicated servers would increase the performance of the site *immensely*. I can't imagine an event that would provide enough traffic to require more than that.
+Moving Django/Gunicorn, Nginx, Redis, Halley, and Postgresql to dedicated
+servers would increase the performance of the site *immensely*. I can't
+imagine an event that would provide enough traffic to require more than that.
-Even if there were an event that needed that kind of throughput, we could easily split the single Halley and Redis servers into multiple load-balanced servers.
+Even if there were an event that needed that kind of throughput, we could
+easily split the single Halley and Redis servers into multiple load-balanced
+servers.
A Work in Progress
------------------
-This new version of A Feed Apart is still being built. I'm learning new things every time I work on it, and I'm sure there's still room for improvement.
+This new version of A Feed Apart is still being built. I'm learning new things
+every time I work on it, and I'm sure there's still room for improvement.
-If you have any questions, advice, or want me to go more in-depth about a specific aspect of the site's backend please let me know!
+If you have any questions, advice, or want me to go more in-depth about
+a specific aspect of the site's backend please let me know!
{% endblock %}
--- a/content/blog/2010/05/mercurial-workflows-stable-default.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/05/mercurial-workflows-stable-default.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Mercurial Workflows: Stable & Default"
snip: "Part 2 of several."
created: 2010-05-17 18:27:00
- categories: ["programming"]
+ flattr: true
%}
{% block article %}
--- a/content/blog/2010/06/mercurial-workflows-translation-branches.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/06/mercurial-workflows-translation-branches.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "Mercurial Workflows: Translation Branches"
snip: "Uncommon but useful."
created: 2010-06-11 08:15:00
- categories: ["programming"]
+ flattr: true
%}
{% block article_class %}with-diagrams{% endblock %}
--- a/content/blog/2010/08/a-git-users-guide-to-mercurial-queues.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/blog/2010/08/a-git-users-guide-to-mercurial-queues.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "A Git User's Guide to Mercurial Queues"
snip: "MQ is git's index on steroids."
created: 2010-08-10 21:00:00
- categories: ["programming"]
+ flattr: true
%}
{% block article_class %}with-diagrams{% endblock %}
@@ -260,7 +260,9 @@
then we're stuck with the powerful-but-sometimes-clumsy MQ interface.
Hopefully this post has given git users (and Mercurial users) an idea of how
-powerful MQ can be. If you have any questions please leave a comment and let
-me know!
+powerful MQ can be. If you have any questions please find me on
+[Twitter][twsl] and me know!
+
+[twsl]: {{links.twsl}}
{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2010/09/making-my-site-sing.html Wed Sep 08 20:15:45 2010 -0400
@@ -0,0 +1,230 @@
+{% extends "_post.html" %}
+
+{% hyde
+ title: "Making My Site Sing"
+ snip: "Designing with music."
+ created: 2010-09-08 20:10:00
+ flattr: true
+%}
+
+{% block article %}
+
+Every year or so I get the urge to redesign my site. It's only been seven
+months since the last time, so I guess working with [Nick Sergeant][] and
+[Ali Ali][] at [Dumbwaiter Design][] has made me less satisfied than usual
+with my previous design.
+
+I didn't switch frameworks this time -- I'm still [using Hyde][] to generate
+a set of flat HTML files. I only changed the structure and layout of the
+rendered site.
+
+I'm a programmer, not a designer, but I think it looks fairly good. I wanted
+to write about how I went about designing the site because it might help other
+programmers.
+
+[Nick Sergeant]: http://nick.sg/
+[Ali Ali]: http://alialithinks.com/
+[Dumbwaiter Design]: http://dwaiter.com/
+[using Hyde]: /blog/2010/01/moving-from-django-to-hyde/
+
+[TOC]
+
+Finding a Starting Point
+------------------------
+
+The first thing I had to do was come up with a basic idea for the style and
+typography of the site.
+
+I decided to go with my usual style: dark text on a light background, very few
+images, and an overall feeling of "minimal." If I had the graphic design
+skills to make something impressive to look at I'd use them, but I don't, so
+I wanted to stick with what I'm good at.
+
+I read a lot of programmers' blogs and one thing that annoys me is that I often
+end up using [Safari Reader][] to make their sites pleasant to read. I want my
+site to be pleasant to read *without* extra tools like Reader, so I took the easy
+route and based the site's typography on Reader itself.
+
+Reader uses 18px [Palatino][] body text with a 25px line height, so that's what
+I went with. I considered using [Georgia][] instead of Palatino, but
+unfortunately Georgia has an absolutely terrible bold weight. I also kept the
+width of the site small to mimic Reader.
+
+[Safari Reader]: http://www.apple.com/safari/whats-new.html#reader
+[Palatino]: http://en.wikipedia.org/wiki/Palatino
+[Georgia]: http://en.wikipedia.org/wiki/Georgia_(typeface)
+
+Creating a Vertical Rhythm
+--------------------------
+
+Once I had a line height in place I could start working on a [vertical rhythm][].
+I used [Aardvark Legs][] as a base stylesheet and edited it to fit the new font
+size and line height.
+
+Unfortunately the original post by Aardvark Legs' author seems to have
+disappeared. In a nutshell: it's a CSS file that helps you set up a consistent
+vertical rhythm.
+
+I tried to keep myself honest by including a tiny bit of Javascript in the
+footer of the site that displays the vertical rhythm. If you click on it you
+should see that everything lines up properly (except the footer itself, which
+falls on a halfway point).
+
+For some entries the rhythm might not be perfect in non-Webkit browsers because
+I had to use some [Webkit-specific styling][scrollbars] to fix the height of
+scrollbars of wide `<pre>` blocks.
+
+[vertical rhythm]: http://www.alistapart.com/articles/settingtypeontheweb/
+[aardvark legs]: http://aardvark.fecklessmind.com/
+[scrollbars]: http://webkit.org/blog/363/styling-scrollbars/
+
+Designing to a Dominant Seventh
+-------------------------------
+
+In my spare time I play upright bass and teach blues dancing. I listen to a lot
+of jazz and blues music while doing both and one of the more common chords in
+those genres is a [dominant seventh][].
+
+What does this have to do with my site's design? Although I had a font size of
+18px for the body text I still needed to decide on sizes for headers and other
+site elements. Dominant seventh chords sound beautiful, so I used the notes in
+the chord to come up with these sizes.
+
+Here are the sizes I came up with (after rounding off to the nearest pixel):
+
+* Root: 18 pixels
+* Major third: 23 pixels
+* Perfect fifth: 27 pixels
+* Minor seventh: 32 pixels
+* Octave: 36 pixels
+* Major tenth: 45 pixels
+
+This gave me a variety of sizes to work with. Here are a few places where
+I used them:
+
+* Base font size: root
+* `h1` elements: major tenth
+* `h2` elements: minor seventh
+* `h3` elements: major third
+* `h4` elements: root
+* "Logo" in the header: major third
+* Navigation links: root
+* Footer text: perfect fifth (an octave down)
+
+You might notice that I don't use a straight perfect fifth anywhere in the
+design. There are two reasons for this.
+
+First: the perfect fifth and the line height I got from Reader are only two
+pixels apart, which would feel dissonant.
+
+Second: the perfect fifth is the most "generic" note in the chord, so
+eliminating it doesn't really change the feeling of the dominant seventh at
+all.
+
+Once I had my line height and header sizes I had plenty to work on. I made
+images, blockquotes, code blocks, and everything else fit the rhythm. After
+that I decided to start playing with some other things.
+
+[dominant seventh]: http://en.wikipedia.org/wiki/Dominant_seventh_chord
+
+Removing Comments
+-----------------
+
+The first thing I did after I got the rhythm of the site down was to remove the
+[Disqus][] comments.
+
+I did this for two reasons. The first and most "practical" reason was that
+they simply looked out of place. It's hard to style content from a third-party
+site to look great with the rhythm of the site so I got rid of it altogether.
+
+The second reason is something I've learned from music and dancing: the most
+important notes are the ones you *don't* play.
+
+I'm usually pretty busy with full-time and freelance work and don't have enough
+time to properly respond to comments on the site. Having comments here,
+then, is like having calls without responses -- it doesn't work very well.
+
+If someone wants to tell me something they can easily find me on
+[Twitter][twsl] and talk to me or discuss a post on [Hacker News][].
+
+[Disqus]: http://disqus.com/
+[twsl]: {{links.twsl}}
+[Hacker News]: http://news.ycombinator.com/
+
+Adding Applause with Flattr
+---------------------------
+
+I've started using [Flattr][] to help show my appreciation to people that make
+good things on the internet. Since I was redesigning the site I figured I'd
+include Flattr buttons on my blog posts.
+
+One reason was simple: it lets people give me money for the things I write.
+Another reason is a bit more altruistic: if more people see Flattr buttons
+around the web more people will sign up and help out creators.
+
+I like to think of Flattr as applause at a jazz show or a dance. It doesn't
+really contribute anything to the conversation but it *does* let you easily
+show your appreciaton.
+
+The worst part of this was going through all my old blog posts and submitting
+them to Flattr.
+
+[Flattr]: http://flattr.com/
+
+Printing Nicely with Print Links
+--------------------------------
+
+This is something that my old site also had but I never really talked about
+(except on [Forrst][]).
+
+If you print one of my site's pages you'll notice that any links inside
+a paragraph of content will show up in a list after the paragraph. I think
+this makes it easier to refer to a printed copy because you can type in the
+URLs without having to visit my site again.
+
+To do this I use [a little bit of Javascript][printjs]. I *could* put the URLs
+directly after the links using just CSS, but I think that breaks up the content
+and makes it harder to read.
+
+[Forrst]: http://forrst.com/
+[printjs]: http://bitbucket.org/sjl/stevelosh/src/tip/media/js/print.js
+
+Showing Context with Scrolly Headers
+------------------------------------
+
+The last trick I pulled out of my sleeve was the "scrolly headers" to the left
+of the content, which you've probably already noticed.
+
+I tend to write fairly long blog posts and I think about their structure quite
+a bit. Now that I'm using a much larger font I feel that it's too easy to get
+lost while reading them. If you switch away from the page for a bit and come
+back you might not remember where you were.
+
+To help fix this I wrote a bit of Javascript to display the top-level headers
+of post content to the left of the content. I think this might help people
+keep their place more easily.
+
+Influences and Goals
+--------------------
+
+While redesigning I had two main influences in mind:
+[Eivind Uggedal's site][uggedal] and [Simon Hørup Eskildsen's site][sirupsen].
+I hope they don't mind that I took a lot of elements from their designs to make
+my own.
+
+As I was making the new site I had a very simple goal: "make sure no one ever
+wants to use Safari Reader on my site."
+
+The design isn't particularly memorable (hell, it pretty much looks like you
+just used Safari Reader), but I don't think that's a problem. I'm not
+a designer so I don't want my site to be remembered for its design. I want it
+to be remembered for the content, so I aimed for a design that highlights that
+content and gets out of the way.
+
+If you have comments, questions, or suggestions feel free to find me on
+[Twitter][twsl].
+
+[uggedal]: http://uggedal.com/
+[sirupsen]: http://sirupsen.com/
+
+{% endblock %}
--- a/content/blog/dancing.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Blog"
- category: "dancing"
- exclude: True
-%}
\ No newline at end of file
--- a/content/blog/music.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Blog"
- category: "music"
- exclude: True
-%}
\ No newline at end of file
--- a/content/blog/photography.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Blog"
- category: "photography"
- exclude: True
-%}
\ No newline at end of file
--- a/content/blog/programming.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Blog"
- category: "programming"
- exclude: True
-%}
\ No newline at end of file
--- a/content/projects/django-hoptoad.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/django-hoptoad.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "django-hoptoad"
snip: "Now ponies can ride the toad too."
created: 2009-07-25 01:16:40
- categories: ["programming"]
%}
{% block article %}
@@ -27,8 +26,9 @@
-----------
This Middleware is a work in progress. If you have a suggestion or find a bug
-please [add an issue][issues] or post a comment and let me know.
+please [add an issue][issues] or find me on [Twitter][twsl] and let me know.
[issues]: http://bitbucket.org/sjl/django-hoptoad/issues/?status=new&status=open
+[twsl]: {{links.twsl}}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/fuego.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/fuego.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "Fuego"
snip: "Photographs of Alex. Studio."
created: 2009-01-19 01:25:20
- categories: ["photography"]
%}
{% block article %}
@@ -34,4 +33,6 @@
{% endspaceless %}
-{% endblock %}
\ No newline at end of file
+Letting go.
+
+{% endblock %}
--- a/content/projects/grabtweets.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/grabtweets.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "grabtweets"
snip: "A simple tool for backing up your tweets."
created: 2009-09-12 11:02:46
- categories: ["programming"]
+ exclude: True
%}
{% block article %}
@@ -79,4 +79,4 @@
[issue tracker]: http://bitbucket.org/sjl/grabtweets/issues/?status=new&status=open
[repository]: http://bitbucket.org/sjl/grabtweets/
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/hg-paste.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/hg-paste.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "hg-paste"
snip: "Send diffs from Mercurial to various pastebin websites."
created: 2009-09-16 17:52:55
- categories: ["programming"]
%}
{% block article %}
@@ -77,4 +76,4 @@
[issues]: http://bitbucket.org/sjl/hg-paste/issues/?status=new&status=open
[repository]: http://bitbucket.org/sjl/hg-paste
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/hg-prompt.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/hg-prompt.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "hg-prompt"
snip: "A Mercurial extension for adding repository info to your shell prompt."
created: 2009-06-19 22:25:17
- categories: ["programming"]
%}
{% block article %}
@@ -29,4 +28,4 @@
not perfect, so if you've got a way to improve it please [add an
issue](http://bitbucket.org/sjl/hg-prompt/issues/) and let me know.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/hgtab.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/hgtab.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "hgtab"
snip: "Smarter tab completion for Mercurial in bash."
created: 2009-03-10 20:22:44
- categories: ["programming"]
exclude: True
%}
@@ -117,4 +116,4 @@
Enjoy!
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/lindyjam-com.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/lindyjam-com.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "lindyjam.com"
snip: "A page for a local weekly swing dance event (and more)."
created: 2009-01-21 18:28:35
- categories: ["programming"]
+ exclude: True
%}
{% block article %}
@@ -150,4 +150,4 @@
If you have any comments or questions about the site please let me know! You
can post them here or [email me][].
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/photography.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Projects"
- category: "photography"
- exclude: True
-%}
\ No newline at end of file
--- a/content/projects/programming.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% extends "skeleton/_categorylisting.html" %}
-
-{% hyde
- title: "Projects"
- category: "programming"
- exclude: True
-%}
\ No newline at end of file
--- a/content/projects/stevelosh-com.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/stevelosh-com.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,7 @@
title: "stevelosh.com"
snip: "This website."
created: 2009-01-11 15:40:26
- categories: ["programming"]
+ exclude: True
%}
{% block article %}
@@ -99,4 +99,4 @@
[Mint]: http://haveamint.com/
[WebFaction]: {{links.webfaction}}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/t.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/t.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "t"
snip: "A command-line todo list manager for people that want to <em>finish</em> tasks, not organize them."
created: 2009-09-11 19:03:29
- categories: ["programming"]
%}
{% block article %}
@@ -252,4 +251,4 @@
[Mercurial repository]: http://bitbucket.org/sjl/t/
[git mirror]: http://github.com/sjl/t/
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/content/projects/women-in-water.html Tue Aug 10 20:58:46 2010 -0400
+++ b/content/projects/women-in-water.html Wed Sep 08 20:15:45 2010 -0400
@@ -4,7 +4,6 @@
title: "Women in Water"
snip: "Photographs of women in Lake Ontario."
created: 2009-08-04 18:57:36
- categories: ["photography"]
%}
{% block article %}
@@ -44,4 +43,4 @@
This is still a work in progress.
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/layout/_post.html Tue Aug 10 20:58:46 2010 -0400
+++ b/layout/_post.html Wed Sep 08 20:15:45 2010 -0400
@@ -10,21 +10,24 @@
<div id="leaf-title">
<h1><a href="{{ page.url }}">{{ page.title|safe|typogrify }}</a></h1>
</div>
-
- <div id="leaf-stats">
+
+
+ <div id="leaf-stats" class="group">
+ {% if page.flattr %}
+ <div class="flattr">
+ <a class="FlattrButton" style="display:none;" rev="flattr;button:compact;"
+ href="http://stevelosh.com{{ page.url }}"></a>
+ </div>
+ {% endif %}
<p>
Posted
<span class="timeago"
title="{{ page.created|date:"Y-m-d" }}T{{ page.created|date:"H:i:s" }}">
</span>
- on {{ page.created|date:"F j, Y" }}
- {% if page.categories %}
- and tagged as
-{% for category in page.categories %}{% if not forloop.first %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}<a href="{{ page.node.ancestors.1.url }}/{{ category }}/">{{ category }}</a>{% endfor %}.
- {% endif %}
+ on {{ page.created|date:"F j, Y" }}.
</p>
</div>
-
+
<div id="leaf-content" class="{% block article_class %}{% endblock %}">
{% filter typogrify %}
{% article %}
@@ -36,16 +39,4 @@
{% endarticle %}
{% endfilter %}
</div>
-
- <h1 id="comment-header">Comments</h1>
-
- <div id="disqus_thread"></div>
- <script type="text/javascript" src="http://disqus.com/forums/stevelosh/embed.js"></script>
- <noscript>
- <p><a href="http://disqus.com/forums/stevelosh/?url=ref">View the discussion thread.</a></p>
- </noscript>
- <a href="http://disqus.com" class="dsq-brlink">
- comments powered by
- <span class="logo-disqus">Disqus</span>
- </a>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/layout/_splash.html Tue Aug 10 20:58:46 2010 -0400
+++ b/layout/_splash.html Wed Sep 08 20:15:45 2010 -0400
@@ -1,15 +1,19 @@
{% extends "skeleton/_base.html" %}
{% block content %}
- {% filter typogrify %}
- <div id="splash-info">
- <ul>
- <li>I like writing. »</li>
- <li>What makes me tick. »</li>
- <li>Some things I’ve made. »</li>
- <li>More about me. »</li>
- <li>Tasty feeds. »</li>
- </ul>
- </div>
- {% endfilter %}
-{% endblock %}
\ No newline at end of file
+ <div class="splash">
+ {% filter typogrify %}
+ <p>Hello, I'm Steve.</p>
+
+ <p>
+ I'm a programmer, photographer, dancer <span class="amp">&</span>
+ bassist from Rochester, New York.
+ </p>
+
+ <p>
+ If you want to get in touch with me,
+ <a href="mailto:steve@stevelosh.com">email</a> is best.
+ </p>
+ {% endfilter %}
+ </div>
+{% endblock %}
--- a/layout/skeleton/_base.html Tue Aug 10 20:58:46 2010 -0400
+++ b/layout/skeleton/_base.html Wed Sep 08 20:15:45 2010 -0400
@@ -1,28 +1,30 @@
{% extends "skeleton/_root.html" %}
-{% block all %}<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+{% block all %}
+<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<html>
<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <link href='http://fonts.googleapis.com/css?family=OFL+Sorts+Mill+Goudy+TT:regular,italic' rel='stylesheet' type='text/css'>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+
<title>{% block title %}{% block extra_title %}{% endblock %}{{ page.title|safe }} / {{ site.name }}{% endblock %}</title>
-
+
{% block feeds %}
<link href="http://feeds2.feedburner.com/stevelosh"
rel="alternate" title="{{ site.name }}"
type="application/atom+xml" />
{% endblock %}
-
+
{% block css %}
- <link rel="stylesheet" href="{{ site.url }}/media/css/aal.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{ site.url }}/media/css/base.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{ site.url }}/media/css/colorbox.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="{{ site.url }}/media/css/print.css" type="text/css" media="print" charset="utf-8" />
+ <link rel="stylesheet" href="/media/css/aal.css" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="/media/css/sjl.css" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="/media/css/colorbox.css" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="/media/css/print.css" type="text/css" media="print" charset="utf-8" />
{% block extra_css %}{% endblock %}
{% endblock %}
-
+
{% block js %}
<script src="/media/js/jquery.js" type="text/javascript"></script>
<script src="/media/js/jquery.timeago.js" type="text/javascript"></script>
@@ -30,40 +32,78 @@
<script src="/media/js/sjl.js" type="text/javascript"></script>
<script src="/media/js/print.js" type="text/javascript"></script>
<script src="http://mint.stevelosh.com/?js" type="text/javascript"></script>
-
+
+ <script type="text/javascript">
+ $(function() {
+ $("a.rhythm").toggle(function() {
+ $("body").addClass("rhythm");
+ }, function() {
+ $("body").removeClass("rhythm");
+ });
+ });
+ </script>
+
+ <script type="text/javascript">
+ /* <![CDATA[ */
+ (function() {
+ var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
+
+ s.type = 'text/javascript';
+ s.async = true;
+ s.src = 'http://api.flattr.com/js/0.5.0/load.js?mode=auto';
+
+ t.parentNode.insertBefore(s, t);
+ })();
+ /* ]]> */
+ </script>
+
{% block extra_js %}{% endblock %}
- {% endblock %}
+ {% endblock %}
<link rel="openid.server" href="http://www.myopenid.com/server" />
<link rel="openid.delegate" href="http://stevelosh.myopenid.com/" />
</head>
-
+
<body>
- <div id="main-wrap">
- <div id="header">
- <h1>
- <a href="/">steve losh</a> <span class="page-title">/ {{ page.title|safe|typogrify }}{% block extra_header %}{% endblock %}</span>
- </h1>
- {% block after_header %}{% endblock %}
+ <div class="wrap">
+ <div class="top group">
+ <header>
+ <a href="/">steve losh</a>
+ </header>
+
+ <nav>
+ <a href="/blog/">Blog</a>
+ <span class="sep">-</span>
+ <a href="/projects">Projects</a>
+ <span class="sep">-</span>
+ <a href="/about/">About</a>
+ <span class="sep">-</span>
+ <a href="http://feeds2.feedburner.com/stevelosh">Feed</a>
+ </nav>
</div>
-
- <div id="nav">
- <ul>
- <li><a href="/blog/">Blog</a></li>
- <li><a href="http://bitbucket.org/sjl/">Code</a></li>
- <li><a href="/projects">Projects</a></li>
- <li><a href="/about/">About</a></li>
- <li><a href="http://feeds2.feedburner.com/stevelosh">Feed</a></li>
- </ul>
- </div>
-
- <div id="content">
+
+ <div class="hr"> </div>
+
+ <div class="content">
{% with page.node.ancestors|last as parent_node %}
{% with parent_node.url as parent_url %}
- {% block content %}{% endblock %}
+ {% block content %}{% endblock %}
{% endwith %}
{% endwith %}
</div>
+
+ <div class="hrb"> </div>
+
+ <footer>
+ I'm also on
+ <a href="http://bitbucket.org/sjl/">BitBucket</a>,
+ <a href="http://github.com/sjl/">GitHub</a>,
+ <a href="http://twitter.com/stevelosh/">Twitter</a>,
+ <a href="http://forrst.com/people/stevelosh/">Forrst</a>
+ and
+ <a href="http://flickr.com/photos/sjl7678/">Flickr</a>.
+ I've got <a href="#" class="rhythm">rhythm</a>.
+ </footer>
</div>
</body>
</html>
--- a/layout/skeleton/_categorylisting.html Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-{% extends "skeleton/_base.html"%}
-
-{% block extra_title %}{{ page.category|capfirst }} / {% endblock %}
-{% block extra_header %} / {{ page.category }}{% endblock %}
-
-{% block content %}
- <div id="section-listing">
- <ol>
- {% with page.node.ancestors|last as cat_root_node %}
- {% for cat_name, cat in cat_root_node.categories.items %}
- {% ifequal cat_name page.category %}
- {% for list_page in cat.posts|dictsortreversed:"created" %}
- {% if not list_page.exclude %}
- {% include "skeleton/_listingitem.html" %}
- {% endif %}
- {% endfor %}
- {% endifequal %}
- {% endfor %}
- {% endwith %}
- </ol>
- </div>
-{% endblock %}
\ No newline at end of file
--- a/layout/skeleton/_listing.html Tue Aug 10 20:58:46 2010 -0400
+++ b/layout/skeleton/_listing.html Wed Sep 08 20:15:45 2010 -0400
@@ -1,30 +1,11 @@
{% extends "skeleton/_base.html"%}
-{% block extra_header %}{% if page.node.categories %} / {% endif %}{% endblock %}
-
-{% block after_header %}
- {% if page.node.categories %}
- <div id="section-tags">
- <div class="section-tags-col">
- {% for category in page.node.categories.keys %}
- <p><a href="{{ page.url }}{{ category }}">{{ category }}</a></p>
- {% if forloop.counter|divisibleby:2 %}
- {% if not forloop.last %}
- </div><div class="section-tags-col">
- {% endif %}
- {% endif %}
- {% endfor %}
- </div>
- </div>
- {% endif %}
-{% endblock %}
-
{% block content %}
- <div id="section-listing">
- <ol>
+ <div class="section-listing">
+ <ol class="group">
{% for node in page.node.walk reversed %}
{% include "skeleton/_innerlisting.html" %}
{% endfor %}
</ol>
</div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/layout/skeleton/_listingitem.html Tue Aug 10 20:58:46 2010 -0400
+++ b/layout/skeleton/_listingitem.html Wed Sep 08 20:15:45 2010 -0400
@@ -5,4 +5,4 @@
{%endwith%}
</a>
<span class="snip">{{ list_page.snip|safe|typogrify }}</span>
-</li>
\ No newline at end of file
+</li>
--- a/media/css/aal.css Tue Aug 10 20:58:46 2010 -0400
+++ b/media/css/aal.css Wed Sep 08 20:15:45 2010 -0400
@@ -1,14 +1,8 @@
-/* @override http://localhost:8080/media/css/aal.css */
/*
- aardvark.legs by Anatoli Papirovski - http://fecklessmind.com/
+ aardvark.legs originally by Anatoli Papirovski - http://fecklessmind.com/
Licensed under the MIT license. http://www.opensource.org/licenses/mit-license.php
*/
-/*
- edited for stevelosh.com by Steve Losh
- changes:
- base font-size was changed to 14px
-
/*
Reset first. Modified version of Eric Meyer and Paul Chaplin reset
from http://meyerweb.com/eric/tools/css/reset/
@@ -25,54 +19,61 @@
header, nav, section, article, aside, footer
{border: 0; margin: 0; outline: 0; padding: 0; background: transparent; vertical-align: baseline;}
+article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
+ display:block;
+}
+
blockquote, q {quotes: none;}
blockquote:before,blockquote:after,q:before,q:after {content: ''; content: none;}
header, nav, section, article, aside, footer {display: block;}
/* Basic styles */
-body {background: #fff; color: #000; font: 0.875em/1.5em Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif;}
-html>body {font-size: 14px;}
+html {overflow-y: scroll;}
+body {background: #fdfdfd; color: #353535; font: normal 18px/25px Palatino, "Palatino Linotype", serif; text-rendering: optimizeLegibility;}
+html>body {font-size: 18px; line-height: 25px;}
img {display: inline-block; vertical-align: bottom;}
h1,h2,h3,h4,h5,h6,strong,b,dt,th {font-weight: 700;}
address,cite,em,i,caption,dfn,var {font-style: italic;}
-h1 {margin: 0 0 0.75em; font-size: 2em;}
-h2 {margin: 0 0 1em; font-size: 1.5em;}
-h3 {margin: 0 0 1.286em; font-size: 1.167em;}
-h4 {margin: 0 0 1.5em; font-size: 1em;}
-h5 {margin: 0 0 1.8em; font-size: .834em;}
-h6 {margin: 0 0 2em; font-size: .75em;}
+h1 { font-size: 45px; line-height: 50px; margin: 25px 0; }
+h2 { font-size: 32px; line-height: 50px; margin: 25px 0; }
+h3 { font-size: 23px; line-height: 25px; margin: 25px 0; }
+h4 {margin: 0 0 22px; font-size: 16px; line-height: 22px;}
+h5 {margin: 0 0 22px; font-size: 14px; line-height: 22px;}
+h6 {margin: 0 0 22px; font-size: 12px; line-height: 22px;}
-p,ul,ol,dl,blockquote,pre {margin: 0 0 1.5em;}
+p,ul,ol,dl,blockquote,pre {margin: 0 0 25px;}
li ul,li ol {margin: 0;}
ul {list-style: outside disc;}
ol {list-style: outside decimal;}
-li {margin: 0 0 0 3em;}
-dd {padding-left: 1.5em;}
-blockquote {padding: 0 1.5em;}
+li {margin: 0 0 0 44px;}
+dd {padding-left: 25px;}
+blockquote {padding: 0 25px;}
a {text-decoration: underline;}
a:hover {text-decoration: none;}
abbr,acronym {border-bottom: 1px dotted; cursor: help;}
del {text-decoration: line-through;}
ins {text-decoration: overline;}
-sub {font-size: .834em; line-height: 1em; vertical-align: sub;}
-sup {font-size: .834em; line-height: 1em; vertical-align: super;}
+sub {font-size: 14px; line-height: 25px; vertical-align: sub;}
+sup {font-size: 14px; line-height: 25px; vertical-align: super;}
-tt,code,kbd,samp,pre {font-size: 1em; font-family: "Courier New", Courier, monospace;}
+tt,code,kbd,samp,pre {font-size: 14px; line-height: 25px; font-family: Menlo, Monaco, Consolas, "Courier New", monospace;}
/* Table styles */
+/* TODO */
table {border-collapse: collapse; border-spacing: 0; margin: 0 0 1.5em;}
caption {text-align: left;}
th, td {padding: .25em .5em;}
-tbody td, tbody th {border: 1px solid #000;}
+tbody td, tbody th {border: 1px solid #222;}
tfoot {font-style: italic;}
/* Form styles */
+/* TODO */
fieldset {clear: both;}
legend {padding: 0 0 1.286em; font-size: 1.167em; font-weight: 700;}
fieldset fieldset legend {padding: 0 0 1.5em; font-size: 1em;}
@@ -101,5 +102,14 @@
form.horizontal .field label {display: inline; float: left; width: 140px; margin-left: -150px;}
/* Useful classes */
+/* TODO */
img.left {display: inline; float: left; margin: 0 1.5em .75em 0;}
-img.right {display: inline; float: right; margin: 0 0 .75em .75em;}
\ No newline at end of file
+img.right {display: inline; float: right; margin: 0 0 .75em .75em;}
+.group:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+}
+
--- a/media/css/base.less Tue Aug 10 20:58:46 2010 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-@pink: #e50053;
-@bodytext: #111111;
-
-/* Main layout styles. */
-html {
- overflow-y: scroll;
-}
-body {
- font-family: "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
- text-rendering: optimizeLegibility;
- color: @bodytext;
-}
-div#main-wrap {
- width: 62em;
- margin: 0 auto;
- margin-bottom: 5em;
-}
-div#content {
- width: 48em;
-}
-div#header {
- margin-bottom: 1.5em;
- overflow: visible;
- white-space: nowrap;
-
- h1 {
- margin-top: 0.5em;
- margin-bottom: 0;
- letter-spacing: -3px;
- font-size: 3em;
- font-weight: normal;
- font-family: "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
- display: inline;
- line-height: 1.5em;
- }
-
- span.page-title {
- color: #666;
- text-transform: lowercase;
- }
-}
-div#nav {
- float: right;
- width: 10em;
- font-size: 1.5em;
- font-weight: bold;
- line-height: 2em;
- -webkit-text-size-adjust: 100%;
-
- ul {
- li {
- list-style: none;
- border-bottom: 1px solid #eee;
- }
-
- li:last-child {
- border-bottom: none;
- }
- }
-
- a {
- border: none;
- font-style: normal;
- color: @bodytext;
- }
-
- a:hover {
- color: @pink;
- text-decoration: none;
- }
-}
-div#splash-info {
- font-size: 1.5em;
- line-height: 2em;
- text-align: right;
- color: #888;
- font-family: "Helvetica Neue Light", HelveticaNeue-Light, Arial, Helvetica, sans-serif;
- -webkit-text-size-adjust: 100%;
-
- ul li {
- margin: 0;
- list-style: none;
- border-bottom: 1px solid #eee;
- }
-
- ul li:last-child {
- border-bottom: none;
- }
-}
-div#section-listing {
- font-size: 1.5em;
- font-weight: bold;
- line-height: 2em;
- color: #888;
- -webkit-text-size-adjust: 100%;
-
- ol {
- list-style: none;
-
- li {
- border-bottom: 1px solid #eee;
- margin: 0;
-
- a {
- color: @bodytext;
- }
-
- a:hover {
- color: @pink;
- text-decoration: none;
- }
-
- span.snip {
- font-size: 0.65em;
- line-height: 1em;
- margin-left: 0.5em;
- font-weight: normal;
- }
- }
-
- li:last-child {
- border-bottom: none;
- }
- }
-}
-
-/* Link styles. */
-a {
- text-decoration: none;
- color: @pink;
-}
-a:hover {
- text-decoration: underline;
-}
-h1, h2, h3, h4, h5, h6 {
- a {
- color: @bodytext;
- }
-
- a:hover {
- color: @pink;
- text-decoration: none;
- }
-}
-
-/* Code styles. */
-code, pre {
- font-family: Consolas, Monaco, "Courier New", monospace;
- font-size: 12px;
- line-height: 21px;
-}
-p code, li code {
- border: 1px solid #ccc;
- background-color: #fafafa;
- padding: 1px 3px;
- white-space: nowrap;
-}
-pre {
- border: 1px solid #ccc;
- background-color: #fafafa;
- padding: 0px 5px;
- margin-left: 2em;
- overflow: auto;
-}
-.dsq-comment-message code {
- display: block;
- white-space: pre;
- border: 1px solid #ccc;
- background-color: #fafafa;
- padding: 0px 5px;
- margin-left: 2em;
- overflow: auto;
-}
-
-/* Quoting styles. */
-blockquote {
- border: 1px solid #ccc;
- background-color: #fafafa;
- padding: 0px 5px;
- margin-left: 2em;
- overflow: auto;
-
- p:last-child {
- margin-bottom: 0;
- }
-}
-span.dquo {
- margin-left: -0.23em;
-}
-
-/* Table of Contents styles. */
-div.toc {
- ul {
- list-style: none;
- }
-
- ul:first-child>li {
- margin-left: 0em;
- }
-}
-
-/* Ampersand styles. */
-span.amp {
- font-family: "Palatino", "Constantia", "Palatino Linotype", serif;
- font-style: italic;
-}
-div#section-listing ol li a span.amp {
- font-weight: bold;
- line-height: 0.85em;
- font-size: 1.1em;
- color: inherit;
-}
-h1, h2, h3, h4, h5, h6 {
- span.amp {
- font-weight: bold;
- line-height: 0.5em;
- font-size: 1.1em;
- color: inherit;
- }
-}
-span.page-title span.amp {
- font-weight: normal;
- font-size: 1em;
- line-height: 0.5em;
-}
-
-/* Article styles. */
-div#leaf-stats p {
- color: #666;
- margin-top: -1em;
- margin-bottom: 1em;
-}
-
-/* Image styles. */
-div#leaf-content {
- img {
- display: block;
- margin-left: auto;
- margin-right: auto;
- border: 1.43em solid #e5e5e5;
- padding: 1px;
- background: black;
- }
- img.left, img.right {
- border: none;
- background: none;
- padding: none;
- }
- img.left {
- margin: 0 1.5em 1em 0;
- }
- img.right {
- margin: 0 0 .75em 1em;
- }
- div.gallery img {
- background: none;
- padding: 0;
- border: none;
- display: inline;
- margin-bottom: 1.5em;
- margin-right: 1.5em;
- }
-}
-div#leaf-content.with-diagrams img {
- display: block;
- margin-left: auto;
- margin-right: auto;
- background: none;
- border: none;
-}
-
-/* Comment styles. */
-h1#comment-header {
- margin-top: 1.5em;
-}
-div#disqus_thread {
- ul#dsq-comments li div div {
- font-size: 14px;
- }
- ul#dsq-comments li {
- margin-bottom: 2em;
- }
- div.dsq-comment-message blockquote {
- margin-bottom: 0em;
- }
-}
-div#dsq-comments-title h3 {
- font-size: 14px;
- font-weight: normal;
- color: #666;
- margin-top: -1em;
- margin-bottom: 1em;
-}
-div.dsq-options {
- display: none;
-}
-div#content div#disqus_thread ul#dsq-comments li div table tbody tr {
- background: #eee;
-}
-div#content div#disqus_thread ul#dsq-comments li div table {
- background: #e5e5e5;
- border: 1px solid #bbb;
-}
-div#dsq-new-post.dsq-post-area {
- margin-top: 2.25em;
-}
-div#dsq-thread-settings.dsq-thread-settings {
- margin-top: 2em;
- margin-bottom: 0em;
- font-size: 14px;
-}
-div#disqus_thread table tbody tr td.dsq-request-user-name small,
-#dsq-new-post div.dsq-request-user-info a {
- font-size: 14px;
-}
-
-/* Tag styles. */
-div#section-tags {
- margin: 0 0 0 0.4em;
- display: inline-block;
- font-family: "Helvetica Neue Light", HelveticaNeue-Light, "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
- p {
- font-size: 1.1em;
- line-height: 1.05em;
- margin: 0;
-
- a {
- color: #666;
- }
- a:hover {
- color: @pink;
- text-decoration: none;
- }
- }
- div.section-tags-col {
- display: inline-block;
- margin-right: 1em;
- }
-}
-
-/* Print link styles */
-.print-links {
- display: none;
-}
--- a/media/css/print.less Tue Aug 10 20:58:46 2010 -0400
+++ b/media/css/print.less Wed Sep 08 20:15:45 2010 -0400
@@ -1,34 +1,18 @@
body {
- font: normal 10pt/1.25 HelveticaNeue, "Helvetica Neue", Arial, Helvetica, sans-serif;
+ font: normal 10pt/1.25 Palatino, "Palatino Linotype";
text-rendering: optimizeLegibility;
}
-#nav, #leaf-title, #comment-header, #disqus_thread, .dsq-brlink, .toc {
+nav, header, .toc {
display: none;
}
-#header {
- font-size: 0.85em;
- text-transform: capitalize;
-
- a, a:active, a:visited {
+#leaf-title {
+ a {
text-decoration: none;
color: black;
}
}
-#leaf-title {
- display: none;
-}
-#leaf-stats {
- a {
- text-decoration: underline;
- color: #c06;
- }
-}
#leaf-content {
- a {
- text-decoration: underline;
- color: #c06;
- }
ul.print-links {
display: block;
font-size: 1em;
@@ -75,3 +59,13 @@
font-family: "Palatino", "Constantia", "Palatino Linotype", serif;
font-style: italic;
}
+.flattr {
+ display: none;
+}
+a {
+ text-decoration: underline;
+ color: #c06;
+}
+footer {
+ display: none;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/media/css/sjl.less Wed Sep 08 20:15:45 2010 -0400
@@ -0,0 +1,312 @@
+@c-link: #e50053;
+@c-body: #222;
+@w-body: 612px;
+@font-fancy: 'OFL Sorts Mill Goudy', 'OFL Sorts Mill Goudy TT', serif;
+
+html {
+ overflow-y: scroll;
+}
+body {
+ text-rendering: optimizeLegibility;
+ color: @c-body;
+ position: relative;
+
+ &.rhythm {
+ background: transparent url("/media/images/rhythm.png") top left;
+ }
+
+ a {
+ text-decoration: none;
+ color: @c-link;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ h1, h2, h3, h4, h5, h6 {
+ font-family: @font-fancy;
+ font-weight: normal;
+
+ a {
+ color: @c-body;
+
+ &:hover {
+ color: @c-link;
+ text-decoration: none;
+ }
+ }
+ .amp {
+ font-style: italic;
+ }
+ }
+ h1 { font-size: 45px; line-height: 50px; margin: 25px 0; } // 3
+ h2 { font-size: 32px; line-height: 50px; margin: 25px 0; } // m7
+ h3 { font-size: 23px; line-height: 25px; margin: 25px 0; } // 3
+ h3 { font-size: 18px; line-height: 25px; margin: 25px 0; } // r
+ code, pre {
+ font-family: Consolas, Menlo, "Courier New", monospace;
+ font-size: 14px;
+ }
+ .codehilite {
+ code, pre {
+ font-family: Consolas, Menlo, "Courier New", monospace;
+ font-size: 16px;
+ line-height: 25px;
+
+ overflow-x: auto;
+
+ border: 1px solid #d5d5d5;
+ border-left: 10px solid #d5d5d5;
+ background-color: #fafafa;
+
+ padding: 11px 15px 12px;
+ margin-left: -25px;
+ }
+ pre::-webkit-scrollbar {
+ height: 25px;
+ }
+ pre::-webkit-scrollbar-button:start,
+ pre::-webkit-scrollbar-button:end {
+ display: none;
+ }
+ pre::-webkit-scrollbar-track-piece {
+ background-color: #eee;
+ }
+ pre::-webkit-scrollbar-thumb {
+ background-color: #bbb;
+ border: 7px solid #eee;
+ -webkit-background-clip: padding-box;
+ -webkit-border-radius: 12px;
+ }
+ }
+ p code, li code {
+ border: 1px solid #ccc;
+ background-color: #fafafa;
+ font-size: 13px;
+ padding: 1px 3px;
+ line-height: 20px;
+ margin: 0;
+ white-space: nowrap;
+ }
+
+ .wrap {
+ width: @w-body;
+ margin: 0 auto;
+ margin-bottom: 5em;
+
+ .top {
+ header {
+ float: left;
+ font-family: @font-fancy;
+ font-size: 23px; // 3
+ line-height: 50px;
+ text-transform: lowercase;
+ padding-left: 2px;
+ width: 612px - 2px - 400px;
+
+ .amp {
+ font-style: italic;
+ }
+ a {
+ color: @c-body;
+
+ &:hover {
+ color: @c-link;
+ }
+ }
+ }
+ nav {
+ font: normal 18px/50px @font-fancy; // 1
+ text-align: right;
+ text-transform: lowercase;
+ padding-right: 2px;
+ width: 400px - 2px;
+ float: left;
+
+ .sep {
+ padding: 0 4px;
+ color: #666;
+ }
+ }
+ }
+ .hr {
+ margin-top: -12px;
+ margin-bottom: 12px + 25px;
+ height: 25px;
+ background: transparent url('/media/images/hr.png') top left no-repeat;
+ }
+ .hrb {
+ height: 25px;
+ margin-top: 50px;
+ background: transparent url('/media/images/hrb.png') top left no-repeat;
+ }
+ footer {
+ font-size: 14px;
+ font-style: italic;
+ line-height: 50px;
+ text-align: center;
+ }
+ }
+}
+.splash {
+ color: #454545;
+ text-align: center;
+ font: normal 45px/50px @font-fancy;
+ margin-bottom: -1px;
+ padding-top: 25px;
+
+ p {
+ margin-bottom: 50px;
+ }
+ .amp {
+ font-style: italic;
+ }
+}
+.section-listing {
+ margin-bottom: -50px;
+ ol {
+ list-style-type: none;
+
+ @w-listing-item: 612px/2;
+ @w-listing-col-padding: 50px;
+
+ li {
+ float: left;
+ width: @w-listing-item - (@w-listing-col-padding / 2);
+ height: 150px;
+ margin: 0;
+ text-align: center;
+
+ a {
+ font: normal 23px/32px @font-fancy; // 3
+ color: @c-body;
+ display: block;
+
+ &:hover {
+ color: @c-link;
+ text-decoration: none;
+ }
+ }
+
+ span.snip {
+ font-size: 18px; // 1
+ color: #333;
+ font-family: @font-fancy;
+ line-height: 25px;
+ font-style: italic;
+ }
+ .amp {
+ font-style: italic;
+ }
+
+ &:nth-child(odd) {
+ margin-right: @w-listing-col-padding / 2;
+ }
+ &:nth-child(even) {
+ margin-left: @w-listing-col-padding / 2;
+ }
+ }
+ }
+}
+
+blockquote {
+ border: 1px solid #ccc;
+ background-color: #fafafa;
+ padding: 0px 5px;
+ margin-left: 2em;
+ overflow: auto;
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+}
+span.dquo {
+ margin-left: -0.23em;
+}
+
+#leaf-stats p {
+ color: #666;
+ margin-top: -22px;
+ margin-bottom: 22px;
+}
+#leaf-content {
+ img {
+ display: block;
+ margin: 25px auto 26px;
+ border: 11px solid #e5e5e5;
+ padding: 1px;
+ background: black;
+ }
+ img.left, img.right {
+ border: none;
+ background: none;
+ padding: none;
+ }
+ img.left {
+ margin: 0 1.5em 1em 0;
+ }
+ img.right {
+ margin: 0 0 .75em 1em;
+ }
+ .gallery img {
+ background: none;
+ padding: 0;
+ border: none;
+ display: inline;
+ margin-bottom: 25px;
+ margin-right: 25px;
+ }
+ .toc {
+ ul {
+ list-style: none;
+ }
+
+ ul:first-child>li {
+ margin-left: 0em;
+ }
+ }
+}
+#leaf-content.with-diagrams img {
+ display: block;
+ margin: 25px auto;
+ padding: 0;
+ background: none;
+ border: none;
+}
+
+.print-links {
+ display: none;
+}
+img.self {
+ border: none;
+ padding: 0;
+ margin: 0;
+ margin-right: -108px;
+ margin-top: -15px;
+ margin-left: 30px;
+ margin-bottom: 20px;
+}
+
+div#cboxCurrent {
+ bottom: -30px;
+ font-size: 17px;
+ font-weight: normal;
+ left: 60px;
+}
+
+#scrolling-header {
+ color: #999;
+ font-size: 23px;
+ font-style: italic;
+ font: italic 23px @font-fancy;
+ line-height: 30px;
+ position: fixed;
+ top: 75px;
+ text-align: right;
+ width: 180px;
+}
+
+.flattr {
+ float: right;
+ padding-top: 1px;
+}
Binary file media/images/blog/2009/02/dj-playlist-sorting.png has changed
Binary file media/images/blog/2009/02/dj-playlist-unrated.png has changed
Binary file media/images/blog/2009/08/branch-anon.png has changed
Binary file media/images/blog/2009/08/branch-base.png has changed
Binary file media/images/blog/2009/08/branch-bookmark.png has changed
Binary file media/images/blog/2009/08/branch-clone.png has changed
Binary file media/images/blog/2009/08/branch-named.png has changed
Binary file media/images/blog/2010/01/mercurial-vs-git.jpg has changed
Binary file media/images/blog/2010/02/hg-branching-1-after-merge.png has changed
Binary file media/images/blog/2010/02/hg-branching-1-needs-merge.png has changed
Binary file media/images/blog/2010/02/hg-branching-1-start.png has changed
Binary file media/images/blog/2010/02/zsh-prompt-comments.png has changed
Binary file media/images/blog/2010/02/zsh-prompt.png has changed
Binary file media/images/blog/2010/05/default-stable-example.png has changed
Binary file media/images/blog/2010/06/translation-branches.png has changed
Binary file media/images/blog/2010/08/git-basics.png has changed
Binary file media/images/blog/2010/08/mercurial-basics.png has changed
Binary file media/images/blog/2010/08/mq-multiple.png has changed
Binary file media/images/blog/2010/08/mq-one.png has changed
Binary file media/images/blog/2010/08/mq-two.png has changed
Binary file media/images/blog/2010/08/mq-versioned.png has changed
Binary file media/images/colorbox/border.png has changed
Binary file media/images/colorbox/controls.png has changed
Binary file media/images/hr.png has changed
Binary file media/images/hrb.png has changed
Binary file media/images/rhythm.png has changed
Binary file media/images/self.jpg has changed
--- a/media/js/sjl.js Tue Aug 10 20:58:46 2010 -0400
+++ b/media/js/sjl.js Wed Sep 08 20:15:45 2010 -0400
@@ -1,7 +1,57 @@
-$(function() {
- jQuery('span.timeago').timeago();
-});
+var h2s = null;
+
+function place_scrolly_header () {
+ var soff = 75;
+
+ var y = $(window).scrollTop();
+
+ var target_content = null;
+ var opacity = null;
+ var header_y = null;
+ h2s.each(function() {
+ var pre_header_y = $(this).position()['top'] - soff;
+ if (y < pre_header_y) {
+ return false;
+ };
+ header_y = pre_header_y;
+
+ target_content = $(this).html().replace(/ /g, ' ');
+
+ var opacity_y = y - (header_y + soff);
+ opacity = opacity_y / soff;
+ if (opacity > 1.0) {
+ opacity = 1.0;
+ }
+
+ if (opacity > 0.99) {
+ var next_headers = $(this).nextAll('h2');
+ if (next_headers.length) {
+ var next_header_y = next_headers.first().position()['top'];
+ var next_header_distance = next_header_y - y;
+ if (next_header_distance <= soff*2) {
+ opacity = 1.0 / (soff - next_header_distance/2);
+ };
+ }
+ }
+ });
+ $('#scrolling-header').css({ opacity: opacity })
+ .css('left', h2s.first().position()['left'] - 180 - 35)
+ .html(target_content);
+}
$(function() {
- $("div.gallery a").colorbox();
-});
\ No newline at end of file
+ jQuery('span.timeago').timeago();
+
+ if ($('.gallery a').length) {
+ $('.gallery a').colorbox();
+ }
+
+ if ($('#leaf-stats').length) {
+ $('body').append('<div id="scrolling-header"></div>');
+ h2s = $('#leaf-content h2');
+
+ $(window).scroll(function () {
+ place_scrolly_header();
+ });
+ }
+});
--- a/settings.py Tue Aug 10 20:58:46 2010 -0400
+++ b/settings.py Wed Sep 08 20:15:45 2010 -0400
@@ -27,11 +27,11 @@
# {folder : extension : (processors)}
# The processors are run in the given order and are chained.
-# Only a lone * is supported as an indicator for folders. Path
+# Only a lone * is supported as an indicator for folders. Path
# should be specified. No wildcard card support yet.
-
-# Starting under the media folder. For example, if you have media/css under
-# your site root,you should specify just css. If you have media/css/ie you
+
+# Starting under the media folder. For example, if you have media/css under
+# your site root,you should specify just css. If you have media/css/ie you
# should specify css/ie for the folder name. css/* is not supported (yet).
# Extensions do not support wildcards.
@@ -51,12 +51,6 @@
CONTENT_PROCESSORS = {}
SITE_PRE_PROCESSORS = {
- 'blog': {
- 'hydeengine.site_pre_processors.CategoriesManager': {},
- },
- 'projects': {
- 'hydeengine.site_pre_processors.CategoriesManager': {},
- },
'/': {
'hydeengine.site_pre_processors.NodeInjector' : {
'variable': 'blog_node',
@@ -92,22 +86,23 @@
'lesscss': 'http://lesscss.org/',
'bitbucket': 'http://bitbucket.org/',
'github': 'http://github.com/',
+ 'twsl': 'http://twitter.com/stevelosh/',
},
}
-FILTER = {
+FILTER = {
'include': (".htaccess",),
'exclude': (".*","*~")
-}
+}
# Processor Configuration
YUI_COMPRESSOR = os.path.join(HYDE_FOLDER, 'lib', 'yuicompressor-2.4.1.jar')
HSS_PATH = None # if you don't want to use HSS
-LESS_CSS_PATH = '/Users/sjl/.gem/ruby/1.8/bin/lessc'
-THUMBNAIL_MAX_WIDTH = 140
-THUMBNAIL_MAX_HEIGHT = 300
+LESS_CSS_PATH = '/usr/local/bin/lessc'
+THUMBNAIL_MAX_WIDTH = 1400000000
+THUMBNAIL_MAX_HEIGHT = 100
THUMBNAIL_FILENAME_POSTFIX = '-thumb'
# Django settings