diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d6cb9575..1b0f3da53 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -231,6 +231,18 @@ ENDIF(WIN32)
 OPTION(CONNECTOR_HTTP "Compile in stand-alone httpd connector (libwthttp) ?" ON)
 SET(EXAMPLES_CONNECTOR wthttp CACHE STRING "Connector used for examples")
 
+SET(WT_CPP17_FILESYSTEM_IMPLEMENTATION "boost" CACHE STRING
+  "Implementation for Wt::cpp17::filesystem. Defaults to \"boost\", but can be set to \"std\" for std::filesystem. This is mostly used internally and in the examples.")
+SET_PROPERTY(CACHE WT_CPP17_FILESYSTEM_IMPLEMENTATION PROPERTY STRINGS boost std)
+
+IF (${WT_CPP17_FILESYSTEM_IMPLEMENTATION} STREQUAL "boost")
+  SET(WT_FILESYSTEM_IMPL_BOOST ON)
+ELSEIF(${WT_CPP17_FILESYSTEM_IMPLEMENTATION} STREQUAL "std")
+  SET(WT_FILESYSTEM_IMPL_STD ON)
+ELSE()
+  MESSAGE(FATAL_ERROR "WT_CPP17_FILESYSTEM_IMPLEMENTATION must be boost or std")
+ENDIF()
+
 include (CheckSymbolExists)
 
 find_package(PNG)
diff --git a/WConfig.h.in b/WConfig.h.in
index 3b9841fc1..49ffb648c 100644
--- a/WConfig.h.in
+++ b/WConfig.h.in
@@ -40,6 +40,9 @@
 #cmakedefine WT_ANY_IS_EXPERIMENTAL_ANY
 #cmakedefine WT_ANY_IS_STD_ANY
 
+#cmakedefine WT_FILESYSTEM_IMPL_BOOST
+#cmakedefine WT_FILESYSTEM_IMPL_STD
+
 #cmakedefine WT_ASIO_IS_BOOST_ASIO
 #cmakedefine WT_ASIO_IS_STANDALONE_ASIO
 
diff --git a/cmake/WtFindBoost.txt b/cmake/WtFindBoost.txt
index e86fd7e8a..c315a5799 100644
--- a/cmake/WtFindBoost.txt
+++ b/cmake/WtFindBoost.txt
@@ -52,10 +52,15 @@ SET(Boost_DEBUG ON)
 
 SET(Boost_COMPONENTS
     program_options
-    filesystem
     thread
 )
 
+IF(WT_CPP17_FILESYSTEM_IMPLEMENTATION STREQUAL "boost")
+  SET(Boost_COMPONENTS
+      ${Boost_COMPONENTS}
+      filesystem)
+ENDIF()
+
 function(find_boost_system)
   find_package(Boost 1.50 QUIET
     COMPONENTS
diff --git a/examples/filetreetable/CMakeLists.txt b/examples/filetreetable/CMakeLists.txt
index c0c941004..a62dc5782 100644
--- a/examples/filetreetable/CMakeLists.txt
+++ b/examples/filetreetable/CMakeLists.txt
@@ -1,6 +1,6 @@
-IF(NOT BOOST_FS_LIB)
-  MESSAGE(STATUS "** Not building filetreetable example: requires boost_filesystem library.")
-ELSE(NOT BOOST_FS_LIB)
+IF(NOT (WT_CPP17_FILESYSTEM_IMPLEMENTATION STREQUAL "std" OR BOOST_FS_LIB))
+  MESSAGE(STATUS "** Not building filetreetable example: requires std::filesystem or boost_filesystem library.")
+ELSE()
 
   WT_ADD_EXAMPLE(filetreetable.wt
     FileTreeTable.C
@@ -15,5 +15,5 @@ ELSE(NOT BOOST_FS_LIB)
 
   INCLUDE_DIRECTORIES(${WT_SOURCE_DIR}/src)
 
-ENDIF(NOT BOOST_FS_LIB)
+ENDIF()
 
diff --git a/examples/filetreetable/FileTreeTable.C b/examples/filetreetable/FileTreeTable.C
index 85dc2c935..12ac36346 100644
--- a/examples/filetreetable/FileTreeTable.C
+++ b/examples/filetreetable/FileTreeTable.C
@@ -10,9 +10,11 @@
 
 #include <Wt/WText.h>
 
+#include <Wt/cpp17/filesystem.hpp>
+
 using namespace Wt;
 
-FileTreeTable::FileTreeTable(const boost::filesystem::path& path)
+FileTreeTable::FileTreeTable(const cpp17::filesystem::path& path)
   : WTreeTable()
 {
   addColumn("Size", 80);
diff --git a/examples/filetreetable/FileTreeTable.h b/examples/filetreetable/FileTreeTable.h
index de47d0f96..93922bb77 100644
--- a/examples/filetreetable/FileTreeTable.h
+++ b/examples/filetreetable/FileTreeTable.h
@@ -9,7 +9,7 @@
 
 #include <Wt/WTreeTable.h>
 
-#include <boost/filesystem/path.hpp>
+#include <Wt/cpp17/filesystem.hpp>
 
 /**
  * \defgroup fileexplorer File Explorer example
@@ -37,7 +37,7 @@ public:
    *
    * Create a new FileTreeTable to browse the given path.
    */
-  FileTreeTable(const boost::filesystem::path& path);
+  FileTreeTable(const Wt::cpp17::filesystem::path& path);
 };
 
 /*@}*/
diff --git a/examples/filetreetable/FileTreeTableNode.C b/examples/filetreetable/FileTreeTableNode.C
index 1d4d579a7..99d877ad4 100644
--- a/examples/filetreetable/FileTreeTableNode.C
+++ b/examples/filetreetable/FileTreeTableNode.C
@@ -7,9 +7,6 @@
 
 #include "FileTreeTableNode.h"
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/exception.hpp>
-#include <boost/lexical_cast.hpp>
 #include <iostream>
 
 #include <Wt/WDateTime.h>
@@ -19,7 +16,9 @@
 #include <Wt/WText.h>
 #include <Wt/WAny.h>
 
-FileTreeTableNode::FileTreeTableNode(const boost::filesystem::path& path)
+#include <Wt/cpp17/filesystem.hpp>
+
+FileTreeTableNode::FileTreeTableNode(const cpp17::filesystem::path& path)
 #if BOOST_FILESYSTEM_VERSION < 3
   : WTreeTableNode(Wt::widen(path.leaf()), createIcon(path)),
 #else
@@ -29,15 +28,15 @@ FileTreeTableNode::FileTreeTableNode(const boost::filesystem::path& path)
 {
   label()->setTextFormat(TextFormat::Plain);
 
-  if (boost::filesystem::exists(path)) {
-    if (!boost::filesystem::is_directory(path)) {
-      int fsize = (int)boost::filesystem::file_size(path);
+  if (cpp17::filesystem::exists(path)) {
+    if (!cpp17::filesystem::is_directory(path)) {
+      int fsize = (int)cpp17::filesystem::file_size(path);
       setColumnWidget(1, cpp14::make_unique<WText>(asString(fsize)));
       columnWidget(1)->setStyleClass("fsize");
     } else
       setSelectable(false);
 
-    std::time_t t = boost::filesystem::last_write_time(path);
+    std::time_t t = cpp17::filesystem::last_write_time(path);
     Wt::WDateTime dateTime = Wt::WDateTime::fromTime_t(t);
     Wt::WLocalDateTime localDateTime = dateTime.toLocalTime();
     Wt::WString dateTimeStr = localDateTime.toString(Wt::utf8("MMM dd yyyy"));
@@ -47,10 +46,10 @@ FileTreeTableNode::FileTreeTableNode(const boost::filesystem::path& path)
   }
 }
 
-std::unique_ptr<WIconPair> FileTreeTableNode::createIcon(const boost::filesystem::path& path)
+std::unique_ptr<WIconPair> FileTreeTableNode::createIcon(const cpp17::filesystem::path& path)
 {
-  if (boost::filesystem::exists(path)
-      && boost::filesystem::is_directory(path))
+  if (cpp17::filesystem::exists(path)
+      && cpp17::filesystem::is_directory(path))
     return cpp14::make_unique<WIconPair>("icons/yellow-folder-closed.png",
                          "icons/yellow-folder-open.png", false);
   else
@@ -60,22 +59,22 @@ std::unique_ptr<WIconPair> FileTreeTableNode::createIcon(const boost::filesystem
 
 void FileTreeTableNode::populate()
 {
-  if (boost::filesystem::is_directory(path_)) {
-    std::set<boost::filesystem::path> paths;
-    boost::filesystem::directory_iterator end_itr;
+  if (cpp17::filesystem::is_directory(path_)) {
+    std::set<cpp17::filesystem::path> paths;
+    cpp17::filesystem::directory_iterator end_itr;
 
-    for (boost::filesystem::directory_iterator i(path_); i != end_itr; ++i)
+    for (cpp17::filesystem::directory_iterator i(path_); i != end_itr; ++i)
       try {
 	paths.insert(*i);
-      } catch (boost::filesystem::filesystem_error& e) {
+      } catch (cpp17::filesystem::filesystem_error& e) {
         std::cerr << e.what() << std::endl;
       }
 
-    for (std::set<boost::filesystem::path>::iterator i = paths.begin();
+    for (std::set<cpp17::filesystem::path>::iterator i = paths.begin();
       i != paths.end(); ++i)
       try {
         addChildNode(cpp14::make_unique<FileTreeTableNode>(*i));
-      } catch (boost::filesystem::filesystem_error& e) {
+      } catch (cpp17::filesystem::filesystem_error& e) {
         std::cerr << e.what() << std::endl;
       }
   }
@@ -84,7 +83,7 @@ void FileTreeTableNode::populate()
 bool FileTreeTableNode::expandable()
 {
   if (!populated()) {
-    return boost::filesystem::is_directory(path_);
+    return cpp17::filesystem::is_directory(path_);
   } else
     return WTreeTableNode::expandable();
 }
diff --git a/examples/filetreetable/FileTreeTableNode.h b/examples/filetreetable/FileTreeTableNode.h
index 91d6eb62d..3927d0596 100644
--- a/examples/filetreetable/FileTreeTableNode.h
+++ b/examples/filetreetable/FileTreeTableNode.h
@@ -9,7 +9,7 @@
 
 #include <Wt/WTreeTableNode.h>
 
-#include <boost/filesystem/path.hpp>
+#include <Wt/cpp17/filesystem.hpp>
 
 using namespace Wt;
 
@@ -32,11 +32,11 @@ class FileTreeTableNode : public WTreeTableNode
 public:
   /*! \brief Construct a new node for the given file.
    */
-  FileTreeTableNode(const boost::filesystem::path& path);
+  FileTreeTableNode(const cpp17::filesystem::path& path);
 
 private:
   //! The path.
-  boost::filesystem::path path_;
+  cpp17::filesystem::path path_;
 
   //! Reimplements WTreeNode::populate to read files within a directory.
   virtual void populate() override;
@@ -45,7 +45,7 @@ private:
   virtual bool expandable() override;
 
   //! Create the iconpair for representing the path.
-  static std::unique_ptr<WIconPair> createIcon(const boost::filesystem::path& path);
+  static std::unique_ptr<WIconPair> createIcon(const cpp17::filesystem::path& path);
 };
 
 /*@}*/
diff --git a/examples/gitmodel/CMakeLists.txt b/examples/gitmodel/CMakeLists.txt
index ed557d1f4..95eddcdaf 100644
--- a/examples/gitmodel/CMakeLists.txt
+++ b/examples/gitmodel/CMakeLists.txt
@@ -1,6 +1,6 @@
 IF(NOT WIN32)
 
-IF(BOOST_FS_LIB)
+IF(WT_CPP17_FILESYSTEM_IMPLEMENTATION STREQUAL "std" OR BOOST_FS_LIB)
   WT_ADD_EXAMPLE(gitview.wt
     Git.C
     GitModel.C
@@ -15,11 +15,11 @@ IF(BOOST_FS_LIB)
 
   ADD_DEPENDENCIES(gitview.wt wt ${EXAMPLES_CONNECTOR})
 
-ELSE(BOOST_FS_LIB)
+ELSE()
 
-  MESSAGE(STATUS "** Not building gitmodel example: requires boost_filesystem library.")
+  MESSAGE(STATUS "** Not building gitmodel example: requires std::filesystem or boost_filesystem library.")
 
-ENDIF(BOOST_FS_LIB)
+ENDIF()
 
 ELSE(NOT WIN32)
 
diff --git a/examples/wt-homepage/CMakeLists.txt b/examples/wt-homepage/CMakeLists.txt
index 513bc5700..29e91bffa 100644
--- a/examples/wt-homepage/CMakeLists.txt
+++ b/examples/wt-homepage/CMakeLists.txt
@@ -1,4 +1,4 @@
-IF(BOOST_FS_LIB)
+IF(WT_CPP17_FILESYSTEM_IMPLEMENTATION STREQUAL "std" OR BOOST_FS_LIB)
 
 INCLUDE(CheckFunctionExists)
 
@@ -56,8 +56,8 @@ INCLUDE_DIRECTORIES(
   ../blog
   )
 
-ELSE(BOOST_FS_LIB)
+ELSE()
   
-  MESSAGE(STATUS "** Not building wt-homepage example: requires boost_filesystem library.")
+  MESSAGE(STATUS "** Not building wt-homepage example: requires std::filesystem or boost_filesystem library.")
 
-ENDIF(BOOST_FS_LIB)
+ENDIF()
diff --git a/examples/wt-homepage/ExampleSourceViewer.C b/examples/wt-homepage/ExampleSourceViewer.C
index b904fdafc..253cff487 100644
--- a/examples/wt-homepage/ExampleSourceViewer.C
+++ b/examples/wt-homepage/ExampleSourceViewer.C
@@ -21,20 +21,17 @@
 #include <Wt/WVBoxLayout.h>
 #include <Wt/WViewWidget.h>
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/convenience.hpp>
-#include <boost/algorithm/string.hpp>
+#include <Wt/cpp17/filesystem.hpp>
 
 #include "ExampleSourceViewer.h"
 #include "FileItem.h"
 
-namespace fs = boost::filesystem;
+namespace fs = cpp17::filesystem;
 
 // Same as p.filename() in latest boost::filesystem
 static std::string filename(const fs::path& p)
 {
-#if BOOST_FILESYSTEM_VERSION < 3
+#if defined(BOOST_FILESYSTEM_VERISON) && BOOST_FILESYSTEM_VERSION < 3
   return p.empty() ? std::string() : *--p.end();
 #else
   return p.empty() ? std::string() : (*--p.end()).string();
diff --git a/examples/wt-homepage/ExampleSourceViewer.h b/examples/wt-homepage/ExampleSourceViewer.h
index 10946ef55..fcdc1c82a 100644
--- a/examples/wt-homepage/ExampleSourceViewer.h
+++ b/examples/wt-homepage/ExampleSourceViewer.h
@@ -12,6 +12,8 @@
 #include <Wt/WTreeView.h>
 #include <Wt/WStandardItemModel.h>
 
+#include <Wt/cpp17/filesystem.hpp>
+
 #include "FileItem.h"
 #include "SourceView.h"
 
@@ -40,11 +42,11 @@ private:
   std::shared_ptr<WStandardItemModel> model_;
 
   void cppTraverseDir(WStandardItem* parent,
-		      const boost::filesystem::path& path);
+		      const cpp17::filesystem::path& path);
   void javaTraverseDir(WStandardItem* parent,
-		       const boost::filesystem::path& path);
+		       const cpp17::filesystem::path& path);
   void javaTraversePackages(WStandardItem *parent,
-			    const boost::filesystem::path& srcPath,
+			    const cpp17::filesystem::path& srcPath,
 			    const std::string packageName);
 
   /*! \brief Displayed the currently selected file.
diff --git a/examples/wt-homepage/FileItem.h b/examples/wt-homepage/FileItem.h
index acbd36432..c9361b58e 100644
--- a/examples/wt-homepage/FileItem.h
+++ b/examples/wt-homepage/FileItem.h
@@ -14,9 +14,6 @@
 #include "Wt/WStandardItemModel.h"
 #include "Wt/WString.h"
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/exception.hpp>
-
 using namespace Wt;
 
 /*! \class FileItem
diff --git a/examples/wt-homepage/SourceView.C b/examples/wt-homepage/SourceView.C
index bb28d632b..d3d38d869 100644
--- a/examples/wt-homepage/SourceView.C
+++ b/examples/wt-homepage/SourceView.C
@@ -6,16 +6,17 @@
 
 #include <stdlib.h>
 
-#include <boost/algorithm/string.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/convenience.hpp>
-
 #include <Wt/WApplication.h>
 #include <Wt/WText.h>
 #include <Wt/WImage.h>
 
+#include <Wt/cpp17/filesystem.hpp>
+
+// TODO(Roel): eliminate this boost algorithm string
+#include <boost/algorithm/string.hpp>
+
 using namespace Wt;
-namespace fs = boost::filesystem;
+namespace fs = cpp17::filesystem;
 
 SourceView::SourceView(ItemDataRole fileNameRole,
                        ItemDataRole contentRole,
diff --git a/src/Wt/cpp17/filesystem.hpp b/src/Wt/cpp17/filesystem.hpp
new file mode 100644
index 000000000..baa0032a5
--- /dev/null
+++ b/src/Wt/cpp17/filesystem.hpp
@@ -0,0 +1,34 @@
+// This may look like C code, but it's really -*- C++ -*-
+/*
+ * Copyright (C) 2020 Emweb bv, Herent, Belgium.
+ *
+ * See the LICENSE file for terms of use.
+ */
+#ifndef WT_CPP17_FILESYSTEM_HPP
+#define WT_CPP17_FILESYSTEM_HPP
+
+#include <Wt/WConfig.h>
+
+#if defined(WT_FILESYSTEM_IMPL_BOOST)
+
+#include <boost/filesystem.hpp>
+
+namespace Wt {
+  namespace cpp17 {
+    namespace filesystem = boost::filesystem;
+  }
+}
+
+#elif defined(WT_FILESYSTEM_IMPL_STD)
+
+#include <filesystem>
+
+namespace Wt {
+  namespace cpp17 {
+    namespace filesystem = std::filesystem;
+  }
+}
+
+#endif
+
+#endif // WT_CPP17_FILESYSTEM_HPP
diff --git a/src/web/FileUtils.C b/src/web/FileUtils.C
index 95e3ae277..8c40c5555 100644
--- a/src/web/FileUtils.C
+++ b/src/web/FileUtils.C
@@ -7,7 +7,7 @@
 #include "web/FileUtils.h"
 
 #ifndef WT_HAVE_POSIX_FILEIO
-#include <boost/filesystem/operations.hpp>
+#include "Wt/cpp17/filesystem.hpp"
 #else //WT_HAVE_POSIX_FILEIO
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -22,6 +22,10 @@
 #include <windows.h>
 #endif // WIN32
 
+#ifndef WT_WIN32
+#include <unistd.h>
+#endif // WT_WIN32
+
 #include <fstream>
 
 namespace Wt {
@@ -52,7 +56,7 @@ namespace Wt {
     unsigned long long size(const std::string &file) 
     {
 #ifndef WT_HAVE_POSIX_FILEIO
-      return (unsigned long long) boost::filesystem::file_size(file);
+      return (unsigned long long) Wt::cpp17::filesystem::file_size(file);
 #else //WT_HAVE_POSIX_FILEIO
       struct stat sb;
       if (stat(file.c_str(), &sb) == -1) {
@@ -78,7 +82,14 @@ namespace Wt {
     time_t lastWriteTime(const std::string &file) 
     {
 #ifndef WT_HAVE_POSIX_FILEIO
-      return (unsigned long long)boost::filesystem::last_write_time(file);
+#ifdef WT_FILESYSTEM_IMPL_STD
+      // TODO(Roel): can't convert last_write_time to time_t with GCC?
+      auto ftime = Wt::cpp17::filesystem::last_write_time(file);
+      auto systime = decltype(ftime)::clock::to_sys(ftime);
+      return decltype(ftime)::clock::to_time_t(ftime);
+#else // !WT_FILESYSTEM_IMPL_STD
+      return (unsigned long long)Wt::cpp17::filesystem::last_write_time(file);
+#endif // WT_FILESYSTEM_IMPL_STD
 #else //WT_HAVE_POSIX_FILEIO
       struct stat sb;
       if (stat(file.c_str(), &sb) == -1) {
@@ -94,8 +105,8 @@ namespace Wt {
     bool exists(const std::string &file) 
     {
 #ifndef WT_HAVE_POSIX_FILEIO
-      boost::filesystem::path path(file);
-      return boost::filesystem::exists(path);
+      Wt::cpp17::filesystem::path path(file);
+      return Wt::cpp17::filesystem::exists(path);
 #else //WT_HAVE_POSIX_FILEIO
       struct stat sb;
       return stat(file.c_str(), &sb) != -1;
@@ -105,8 +116,8 @@ namespace Wt {
     bool isDirectory(const std::string &file) 
     {
 #ifndef WT_HAVE_POSIX_FILEIO
-      boost::filesystem::path path(file);
-      return boost::filesystem::is_directory(path);
+      Wt::cpp17::filesystem::path path(file);
+      return Wt::cpp17::filesystem::is_directory(path);
 #else //WT_HAVE_POSIX_FILEIO
       struct stat sb;
       stat(file.c_str(), &sb);
@@ -124,17 +135,17 @@ namespace Wt {
 		   std::vector<std::string> &files) 
     {
 #ifndef WT_HAVE_POSIX_FILEIO
-      boost::filesystem::path path(directory);
-      boost::filesystem::directory_iterator end_itr;
+      Wt::cpp17::filesystem::path path(directory);
+      Wt::cpp17::filesystem::directory_iterator end_itr;
 
-      if (!boost::filesystem::is_directory(path)) {
+      if (!Wt::cpp17::filesystem::is_directory(path)) {
 	std::string error 
 	  = "listFiles: \"" + directory + "\" is not a directory";
 	LOG_ERROR(error);
 	throw WException(error);
       }
       
-      for (boost::filesystem::directory_iterator i(path); i != end_itr; ++i) {
+      for (Wt::cpp17::filesystem::directory_iterator i(path); i != end_itr; ++i) {
 	std::string f = (*i).path().string();
 	files.push_back(f);
       }
diff --git a/src/web/WebController.C b/src/web/WebController.C
index f70cfc5f3..f98c8ea9d 100644
--- a/src/web/WebController.C
+++ b/src/web/WebController.C
@@ -32,7 +32,7 @@
 #include <magick/api.h>
 #endif
 
-#ifndef WT_HAVE_POSIX_FILEIO
+#if !defined(WT_HAVE_POSIX_FILEIO) && defined(WT_FILESYSTEM_IMPL_BOOST)
 // boost bug workaround: see WebController constructor
 #include <boost/filesystem.hpp>
 #endif
@@ -72,7 +72,7 @@ WebController::WebController(WServer& server,
   InitializeMagick(0);
 #endif
 
-#ifndef WT_HAVE_POSIX_FILEIO
+#if !defined(WT_HAVE_POSIX_FILEIO) && defined(WT_FILESYSTEM_IMPL_BOOST)
   // attempted workaround for:
   // https://svn.boost.org/trac/boost/ticket/6320
   // https://svn.boost.org/trac/boost/ticket/4889
