diff --git a/skell.cabal b/skell.cabal
--- a/skell.cabal
+++ b/skell.cabal
@@ -2,7 +2,7 @@
 --  see http://haskell.org/cabal/users-guide/
 
 name:                skell
-version:             0.0.0.0
+version:             0.0.1.0
 synopsis:            An overly complex Haskell web framework.
 description:         
   Skell is a Haskell web framework. Much like an actual skeleton, Skell is both
@@ -34,6 +34,7 @@
     , Web.Skell.Resources
     , Web.Skell.Responsible
     , Web.Skell.Partials
+    , Web.Skell.Saferoute
   -- other-modules:       
   other-extensions:    
       OverloadedStrings
diff --git a/src/Web/Skell/Saferoute.hs b/src/Web/Skell/Saferoute.hs
new file mode 100644
--- /dev/null
+++ b/src/Web/Skell/Saferoute.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- |
+-- Module       : Web.Skell.Saferoute
+-- Description  : Saferoutes for things
+-- Copyright    : 2014, Peter Harpending.
+-- License      : BSD3
+-- Maintainer   : Peter Harpending <pharpend2@gmail.com>
+-- Stability    : experimental
+-- Portability  : archlinux
+--
+
+module Web.Skell.Saferoute where
+
+import qualified Data.Map.Lazy       as M
+import           Data.Monoid
+import qualified Data.Text           as S
+import qualified Data.Text.Lazy      as L
+import           Network.Wai (Response)
+import           Paths_skell
+import qualified Text.Blaze.Html5    as H
+import           Web.Skell.Responsible
+
+-- |The type for a route - just an alias for 'L.Text'
+type Route = L.Text
+
+-- |The type class for a resource.
+class Eq r => Resource r where
+  {-# MINIMAL getRoute, (resourceList | routeResourceMap) #-}
+
+  -- Get the 'Route' for a 'Resource'. This is in place to avoid
+  -- @fmap@ stuff. Giving a 'Resource' to this function will
+  -- invariably return a 'Route', as opposed to 'Maybe Route', which
+  -- would be the case if I used a 'M.Map' lookup.
+  getRoute :: r -> Route
+
+  -- |A list of all of the constructors for your resource type.
+  resourceList :: [r]
+  resourceList = M.elems routeResourceMap
+
+  -- |A map from a route to it's resource.
+  routeResourceMap :: M.Map Route r
+  routeResourceMap = M.fromList [(route, resource) | resource <- resourceList,
+                                                     let route = getRoute resource ]
+
+  -- |Given a 'Route', find the 'Resource' behind it. If the route
+  -- isn't associated with any 'Resource', this returns 'Nothing'.
+  lookupRoute :: Route -> Maybe r
+  lookupRoute route = M.lookup route routeResourceMap
+
+  getUrl :: Resource r => r -> H.AttributeValue
+  getUrl = H.toValue . getRoute
+
+-- |Intercalate slashes, and add one to the front
+slashPrependJoin :: [S.Text] -> S.Text
+slashPrependJoin parts = "/" <> S.intercalate "/" parts
