diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml
index bd8e25d140c62b57a397bad317e980b3471ac518..bded42a27f12bb9cdc0e20d95218b87c4dd7a667 100644
--- a/apps/i2psnark/java/build.xml
+++ b/apps/i2psnark/java/build.xml
@@ -98,10 +98,14 @@
         <copy todir="build/icons/.icons" >
             <fileset dir="../icons/" />
         </copy>
+        <copy todir="build/js/.js" >
+            <fileset dir="../js/" />
+        </copy>
         <war destfile="../i2psnark.war" webxml="../web.xml" >
           <!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
           <classes dir="./build/obj" includes="**/web/*.class" />
             <fileset dir="build/icons/" />
+            <fileset dir="build/js/" />
             <manifest>
                 <attribute name="Implementation-Version" value="${full.version}" />
                 <attribute name="Build-Date" value="${build.timestamp}" />
@@ -113,7 +117,7 @@
     
     <target name="warUpToDate">
         <uptodate property="war.uptodate" targetfile="../i2psnark.war" >
-            <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../icons/* ../web.xml" />
+            <srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../icons/* ../js/* ../web.xml" />
         </uptodate>
     </target>
     
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index beebc226aec95928b5d2f2758a4db0fa8f7d8440..e5db6f6cb7d2f9952571d9b3c648b060990ab529 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -102,7 +102,8 @@ public class I2PSnarkServlet extends Default {
     protected Resource getResource(String pathInContext) throws IOException
     {
         if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
-            pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/"))
+            pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/") ||
+            pathInContext.startsWith("/.js/") || pathInContext.startsWith("/.ajax/"))
             return super.getResource(pathInContext);
         // files in the i2psnark/ directory
         return _resourceBase.addPath(pathInContext);
@@ -151,6 +152,17 @@ public class I2PSnarkServlet extends Default {
         _imgPath = _themePath + "images/";
         // this is the part after /i2psnark
         String path = req.getServletPath();
+
+        // AJAX for mainsection
+        if ("/.ajax/xhr1.html".equals(path)) {
+            resp.setCharacterEncoding("UTF-8");
+            resp.setContentType("text/html; charset=UTF-8");
+            PrintWriter out = resp.getWriter();
+            writeMessages(out);
+            writeTorrents(out, req);
+            return;
+        }
+
         boolean isConfigure = "/configure".equals(path);
         // index.jsp doesn't work, it is grabbed by the war handler before here
         if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || path.equals("/_post") || isConfigure)) {
@@ -208,13 +220,18 @@ public class I2PSnarkServlet extends Default {
         out.write("</title>\n");
                                          
         // we want it to go to the base URI so we don't refresh with some funky action= value
+        int delay = 0;
         if (!isConfigure) {
-            int delay = _manager.getRefreshDelaySeconds();
+            delay = _manager.getRefreshDelaySeconds();
             if (delay > 0)
-                out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
+                //out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
+                out.write("<script src=\"/i2psnark/.js/i2psnark.js\" type=\"text/javascript\"></script>\n");
         }
-        out.write(HEADER_A + _themePath + HEADER_B);
-        out.write("</head><body>");
+        out.write(HEADER_A + _themePath + HEADER_B + "</head>\n");
+        if (isConfigure || delay <= 0)
+            out.write("<body>");
+        else
+            out.write("<body onload=\"initAjax(" + (delay * 1000) + ")\">");
         out.write("<center>");
         if (isConfigure) {
             out.write("<div class=\"snarknavbar\"><a href=\"/i2psnark/\" title=\"");
@@ -249,28 +266,38 @@ public class I2PSnarkServlet extends Default {
         String newURL = req.getParameter("newURL");
         if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
             _manager.addMessage(_("Click \"Add torrent\" button to fetch torrent"));
-        out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
-        List msgs = _manager.getMessages();
-        for (int i = msgs.size()-1; i >= 0; i--) {
-            String msg = (String)msgs.get(i);
-            out.write(msg + "\n");
-        }
-        out.write("</pre></td></tr></table></div>");
+        out.write("<div class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
+
+        writeMessages(out);
 
         if (isConfigure) {
+            // end of mainsection div
             out.write("<div class=\"logshim\"></div></div>\n");
             writeConfigForm(out, req);
             writeTrackerForm(out, req);
         } else {
             writeTorrents(out, req);
-            out.write("</div>\n");
+            // end of mainsection div
+            out.write("</div><div id=\"lowersection\">\n");
             writeAddForm(out, req);
             writeSeedForm(out, req);
             writeConfigLink(out);
+            // end of lowersection div
+            out.write("</div>\n");
         }
         out.write(FOOTER);
     }
 
+    private void writeMessages(PrintWriter out) throws IOException {
+        out.write("<div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
+        List msgs = _manager.getMessages();
+        for (int i = msgs.size()-1; i >= 0; i--) {
+            String msg = (String)msgs.get(i);
+            out.write(msg + "\n");
+        }
+        out.write("</pre></td></tr></table></div>");
+    }
+
     private void writeTorrents(PrintWriter out, HttpServletRequest req) throws IOException {
         /** dl, ul, down rate, up rate, peers, size */
         final long stats[] = {0,0,0,0,0,0};
@@ -1356,7 +1383,7 @@ public class I2PSnarkServlet extends Default {
                   "</form></div></div>");        
     }
     
-    private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
+    private static final int[] times = { 5, 15, 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
 
     private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
         String dataDir = _manager.getDataDir().getAbsolutePath();
diff --git a/apps/i2psnark/js/i2psnark.js b/apps/i2psnark/js/i2psnark.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba0e3f911556e41aa0ca351fb15a6a2eb6712aa5
--- /dev/null
+++ b/apps/i2psnark/js/i2psnark.js
@@ -0,0 +1,37 @@
+//var page = "home";
+function ajax(url,target) {
+  // native XMLHttpRequest object
+  if (window.XMLHttpRequest) {
+    req = new XMLHttpRequest();
+    req.onreadystatechange = function() {ajaxDone(target);};
+    req.open("GET", url, true);
+    req.send(null);
+    // IE/Windows ActiveX version
+  } else if (window.ActiveXObject) {
+    req = new ActiveXObject("Microsoft.XMLDOM");
+    if (req) {
+      req.onreadystatechange = function() {ajaxDone(target);};
+      req.open("GET", url, true);
+      req.send(null);
+    }
+  }
+  //setTimeout("ajax(page,'scriptoutput')", 5000);
+}
+
+function ajaxDone(target) {
+  // only if req is "loaded"
+  if (req.readyState == 4) {
+    // only if "OK"
+    if (req.status == 200) {
+      results = req.responseText;
+      document.getElementById(target).innerHTML = results;
+      document.getElementById("lowersection").style.display="block";
+    } else {
+      document.getElementById(target).innerHTML="<b>Router is down</b>";
+      document.getElementById("lowersection").style.display="none";
+    }
+  }
+}
+
+function requestAjax1() { ajax("/i2psnark/.ajax/xhr1.html", "mainsection"); }
+function initAjax(delayMs) { setInterval(requestAjax1, delayMs);  }