diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 3.1.0
+
+* Drop system-filepath
+
 ## 3.0.1.1
 
 * Fix root links
diff --git a/WaiAppStatic/Listing.hs b/WaiAppStatic/Listing.hs
--- a/WaiAppStatic/Listing.hs
+++ b/WaiAppStatic/Listing.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ViewPatterns #-}
 module WaiAppStatic.Listing
     ( defaultListing
     ) where
@@ -104,7 +105,10 @@
                             Left{} -> H.img ! A.src (H.toValue folderSrc)
                                             ! A.alt "Folder"
                             Right{} -> return ()
-                   let name = either id fileName md
+                   let name =
+                           case either id fileName md of
+                               (fromPiece -> "") -> unsafeToPiece ".."
+                               x -> x
                    let isFile = either (const False) (const True) md
                    H.td (H.a ! A.href (H.toValue $ fromPiece name `T.append` if isFile then "" else "/") $ H.toHtml $ fromPiece name)
                    H.td ! A.class_ "date" $ H.toHtml $
diff --git a/WaiAppStatic/Storage/Filesystem.hs b/WaiAppStatic/Storage/Filesystem.hs
--- a/WaiAppStatic/Storage/Filesystem.hs
+++ b/WaiAppStatic/Storage/Filesystem.hs
@@ -11,10 +11,8 @@
     ) where
 
 import WaiAppStatic.Types
-import Prelude hiding (FilePath)
-import Filesystem.Path.CurrentOS (FilePath, (</>))
-import qualified Filesystem.Path.CurrentOS as F
-import qualified Filesystem as F
+import System.FilePath ((</>))
+import System.Directory (doesFileExist, doesDirectoryExist, getDirectoryContents)
 import Data.List (foldl')
 import Control.Monad (forM)
 import Util
@@ -29,10 +27,11 @@
 import Data.Byteable (toBytes)
 import Crypto.Hash (MD5, Digest)
 import qualified Data.ByteString.Base64 as B64
+import qualified Data.Text as T
 
 -- | Construct a new path from a root and some @Pieces@.
 pathFromPieces :: FilePath -> Pieces -> FilePath
-pathFromPieces = foldl' (\fp p -> fp </> F.fromText (fromPiece p))
+pathFromPieces = foldl' (\fp p -> fp </> T.unpack (fromPiece p))
 
 -- | Settings optimized for a web application. Files will have aggressive
 -- caching applied and hashes calculated, and indices and listings are disabled.
@@ -86,12 +85,12 @@
            -> Piece -- ^ file name
            -> IO (Maybe File)
 fileHelper hashFunc fp name = do
-    efs <- try $ getFileStatus $ F.encodeString fp
+    efs <- try $ getFileStatus fp
     case efs of
         Left (_ :: SomeException) -> return Nothing
         Right fs | isRegularFile fs -> return $ Just File
             { fileGetSize = fromIntegral $ fileSize fs
-            , fileToResponse = \s h -> W.responseFile s h (F.encodeString fp) Nothing
+            , fileToResponse = \s h -> W.responseFile s h fp Nothing
             , fileName = name
             , fileGetHash = hashFunc fp
             , fileGetModified = Just $ modificationTime fs
@@ -117,7 +116,7 @@
 -- exists.
 hashFile :: FilePath -> IO ByteString
 hashFile fp = do
-    h <- Crypto.Hash.Conduit.hashFile (F.encodeString fp)
+    h <- Crypto.Hash.Conduit.hashFile fp
     return $ B64.encode $ toBytes (h :: Digest MD5)
 
 hashFileIfExists :: ETagLookup
@@ -128,12 +127,9 @@
         Right x -> Just x
 
 isVisible :: FilePath -> Bool
-isVisible =
-    go . F.encodeString . F.filename
-  where
-    go ('.':_) = False
-    go "" = False
-    go _ = True
+isVisible ('.':_) = False
+isVisible "" = False
+isVisible _ = True
 
 -- | Get a proper @LookupResult@, checking if the path is a file or folder.
 -- Compare with @webAppLookup@, which only deals with files.
@@ -141,17 +137,18 @@
                  -> FilePath -> Pieces -> IO LookupResult
 fileSystemLookup hashFunc prefix pieces = do
     let fp = pathFromPieces prefix pieces
-    fe <- F.isFile fp
+    fe <- doesFileExist fp
     if fe
         then fileHelperLR hashFunc fp lastPiece
         else do
-            de <- F.isDirectory fp
+            de <- doesDirectoryExist fp
             if de
                 then do
-                    entries' <- fmap (filter isVisible) $ F.listDirectory fp
-                    entries <- forM entries' $ \fp' -> do
-                        let name = unsafeToPiece $ either id id $ F.toText $ F.filename fp'
-                        de' <- F.isDirectory fp'
+                    entries' <- fmap (filter isVisible) $ getDirectoryContents fp
+                    entries <- forM entries' $ \fpRel' -> do
+                        let name = unsafeToPiece $ T.pack fpRel'
+                            fp' = fp </> fpRel'
+                        de' <- doesDirectoryExist fp'
                         if de'
                             then return $ Just $ Left name
                             else do
diff --git a/wai-app-static.cabal b/wai-app-static.cabal
--- a/wai-app-static.cabal
+++ b/wai-app-static.cabal
@@ -1,5 +1,5 @@
 name:            wai-app-static
-version:         3.0.1.1
+version:         3.1.0
 license:         MIT
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
@@ -41,8 +41,6 @@
                    , base64-bytestring         >= 0.1
                    , byteable
                    , cryptohash                >= 0.11
-                   , system-filepath           >= 0.4
-                   , system-fileio             >= 0.3
                    , http-date
                    , blaze-html                >= 0.5
                    , blaze-markup              >= 0.5.1
