Building a basic website with pushstate and ajax

Posted on Saturday February 16, 2013 by Eric Potvin

Last week someone asked me about the pushstate with Ajax and how come when the user refresh the website, a 404 Page not found, shows up. With very specific details, he told me what he needed and how his site should work, so William, here's an answer for you.

First of all, when you when you using the pushstate, you are injecting a URL in the browser without loading the page. So if the user wants to refresh the page, that actual page does not really exists. To fix this, you simply needs to use this in your .htaccess:

In other words, you have to redirect everything to your index.html page. Make sure the file or folder does not exists (for example: JPGs, CSS Files, etc..) otherwise, all your images, css and other files will go to the index.html. Then in your JavaScript you can simply trigger the page load when the browser reloads the page.

Here's a simple solution:


<!DOCTYPE html>
  <title>MySite: Welcome</title>
  <meta charset="utf-8" />
  <script type="text/javascript" src=""></script>
  <script type="text/javascript" src="/site.js"></script>

  <h1>My Site: Where everything is awesome</h1>

  <a href="/">Home</a>
  <a href="/about/">About</a>
  <a href="/contact/">Contact Us</a>

  <p>Welcome to our site!</p>

  copyright © 2013



window.onpopstate = function(event) {
function getContent(u) {
    data: {href: u},
    success: function(result) {
      document.title = result.title;
$(document).ready(function() {
  $.ajaxSetup ({  
    cache: false,
    dataType: 'json',
    type: 'POST',
    url: "/load.php"
  $('nav a').click(function(e) {
    var href = $(this).attr("href");
    history.pushState('', '', href);




Now in your PHP you simple have to get the "href" request variable.

// here you can put your security or replace unwanted characters.
$href = str_replace('/', '', $_REQUEST['href']);

// Your custom function to get the HTML template from your CMS
$content = getContent($href); 

echo json_encode($content);


Now the important part. This will allow you to refresh the page without getting the 404.

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index  
RewriteRule (.*) index.html [NC,QSA,L]