diff --git a/.htaccess.example b/.htaccess.example
new file mode 100644
--- /dev/null
+++ b/.htaccess.example
@@ -0,0 +1,16 @@
+# The following would be used to enable friendly pastebin-style
+# URLs. To enable support for these URLs in slate_permutate, set
+# $clean_urls = TRUE in inc/config.inc.
+
+RewriteEngine on
+
+# If you are serving this out of your home directory, there's a good chance you'll have to uncomment and edit one of the lines below:
+
+# For http://csx.calvin.edu/slate_permutate:
+# RewriteBase /slate_permutate
+
+# For http://ohnopub.net/~ohnobinki/slate_permutate:
+# RewriteBase /~ohnobinki/slate_permutate
+
+RewriteCond %{QUERY_STRING} ^(.*)?$
+RewriteRule ^([0-9]+)$ process.php?s=$1&%1 [L]
diff --git a/inc/class.page.php b/inc/class.page.php
--- a/inc/class.page.php
+++ b/inc/class.page.php
@@ -1,5 +1,15 @@
 trackingcode = '' . "\n"
      . $this->trackingcode;
 
-   page::session_start();
+   self::session_start();
     if($immediate
        && $ntitle != "NOHEAD")
       $this->head();
@@ -161,13 +171,19 @@ class page
 
   public function showSavedScheds($session)
   {
+    global $clean_urls;
+
     echo '
';
     if (isset($session['saved']) && count($session['saved']) > 0)
       {
+	$process_php_s = 'process.php?s=';
+	if ($clean_urls)
+	  $process_php_s = '';
+
 	echo '
Saved Schedules:
';
 	foreach($session['saved'] as $key => $name)
 	  {
-	    echo '
#' . $key . ":\n "
+	    echo '
#' . $key . ":\n "
 	      . htmlentities($name)
 	      . ' 
edit'
 	      . ' 
delete'
diff --git a/inc/config.inc.example b/inc/config.inc.example
new file mode 100644
--- /dev/null
+++ b/inc/config.inc.example
@@ -0,0 +1,28 @@
+
+ *
+ * This file is a part of slate_permutate.
+ *
+ * slate_permutate is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * slate_permutate is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with slate_permutate.  If not, see 
.
+ */
+
+/**
+ * \brief
+ *   Use clean URLs for saved schedules. Default: FALSE.
+ *
+ * Before setting this to TRUE, make sure that you have read and
+ * understood ../.htaccess.example and copied it to ../.htaccess .
+ */
+/* $clean_urls = FALSE; */
diff --git a/input.php b/input.php
--- a/input.php
+++ b/input.php
@@ -48,7 +48,7 @@ var sectionsOfClass = Array();
 $school = $inputPage->get_school();
 if ($school && (!empty($_REQUEST['school']) || $school['id'] != 'default'))
   $_SESSION['school_chosen'] = TRUE;
-if ($_REQUEST['selectschool'] == 1
+if (!empty($_REQUEST['selectschool'])
     || $school['id'] == 'default' && !isset($_SESSION['school_chosen']))
   {
 ?>
diff --git a/process.php b/process.php
--- a/process.php
+++ b/process.php
@@ -62,13 +62,17 @@ if (isset($_GET['debug']))
 
 if(!$DEBUG)
   {
-    if(isset($_GET['s']))
+    $s = FALSE;
+    if (isset($_GET['s']))
+      $s = $_GET['s'];
+
+    if($s !== FALSE)
       {
-	$savedSched = schedule_store_retrieve($schedule_store, $_GET['s']);
+	$savedSched = schedule_store_retrieve($schedule_store, $s);
 	if ($savedSched)
 	  $savedSched->writeoutTables();
 	else
-	  Page::show_404('Unable to find a saved schedule with an ID of ' . $_GET['s'] . '.');
+	  page::show_404('Unable to find a saved schedule with an ID of ' . $s . '.');
       }
     elseif(isset($_GET['del']))
       {
@@ -83,8 +87,18 @@ if(!$DEBUG)
 	header('Location: input.php');
 	exit;
       }
+    elseif (!isset($_POST['postData']))
+      {
+	header('Location: input.php');
+	exit;
+      }
     else
       {
+	/*
+	 * we probably have input from the user and should interpret
+	 * it as a schedule to permutate. Then we should redirect the
+	 * user to the canonical URL for that schedule.
+	 */
 		$allClasses = new Schedule($_POST['postData']['name']);
 	
 		foreach($_POST['postData'] as $class)
@@ -114,6 +128,11 @@ if(!$DEBUG)
 		if ($schedule_id != NULL)
 		  $_SESSION['saved'][$schedule_id] = $allClasses->getName();
 
+		$process_php_s = '';
+		if (!$clean_urls)
+		  $process_php_s = 'process.php?s=';
+		header('Location: ' . $process_php_s . $schedule_id);
+		exit;
 		/*
 		 * writeoutTables() needs to know $schedule_id, so it
 		 * has to be called after we save the schedule. See