8 Essential Features of a Modern Website, or: How to Build a Custom One-Pager

In Technology
Scroll this

I was recently contracted to build a one-page website. It was to serve as little more than a website-as-business-card—something to make a company look (a little more) legit.

I strongly believe that utilizing a CMS like WordPress for a site this simple is overkill. The ongoing maintenance that comes with having a CMS would be more taxing than the site is worth. There are many alternate solutions for a one-page website; some of them are free, although most cost something. For this site, any cost seemed like too much.

At face value, this was not a compelling project. Someone just had to throw something together. But it did get me thinking: if I was going to do it right, which features are must-have in a modern website? I took the project, and in the building of it, I answered that question.

Here’s a demo: https://onepager.peterscene.com

And here’s the full source code at GitHub: https://github.com/jasonpetersen/onepager

With this example in hand, follow along as I detail eight essential features of a modern website.

#1: SSL certificate (HTTPS)

If you’re still thinking that SSL certificates are only for e-commerce sites, think again.

Google has ranked secure websites higher than insecure ones for many years now. But as of 2018, it has gone further and called out insecure websites in the address bar.

If you have a good hosting company, this shouldn’t cost you anything more than two minutes of your time. Let’s Encrypt is a free Certificate Authority embedded in the cPanel of hosts like SiteGround (disclaimer: that’s my host). It’s a one-click SSL install, and you never have to think about it again.

#2: Design dos and don’ts

I don’t want to spend a lot of time on this one. Others who have written similar articles have focused almost exclusively on the topic of design (here, here, here, and here). Ask a dozen designers and you’ll get a dozen opinions.

That said, I’d be derelict in my duty if I didn’t provide a handful of baseline pointers. Here are three.

Responsive design

Here on the doorstep of 2020, it goes without saying that all proper web design must scale to any screen size, big or small. Back when this was a novel concept, the Bootstrap framework made it easy. Today, Bootstrap is by no means necessary. Responsive design isn’t a big mystery. Any developer who knows enough CSS to call themselves a developer could write all the media queries you need in little time.

But Bootstrap does make it easy, and I’m not one for reinventing the wheel. The comprehensive classes offered in this framework come in handy. Yes, it adds to the page load time, but I’m not counting the milliseconds for this kind of site.

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

Put that within your <head> tag and you’re ready to go.

The documentation is extensive. Before you write any new classes in your own CSS file, first check to see if Bootstrap already has you covered.

Google Fonts

Don’t rely on generic web fonts like these. That’s total amateur hour.

Head on over to Google Fonts. Pick two: one serif and one sans serif. Follow the instructions. You’ll end up calling it in your <head> tag. Use the rel=”preload” parameter so as to not hold up the loading of the whole page.

<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto:400,700|Roboto+Slab:700&display=fallback" as="style" onload="this.onload=null;this.rel='stylesheet'">

In your CSS file, apply the sans serif font to your body and the serif font to your <h1> to <h6> tags.

One bit of razzamatazz

I’ve always wanted to use “razzamatazz” in a sentence. #lifegoals

Look, if your site is just text and images—no matter how competently it’s laid out—no one will remember it. It needs something extra, and a little dab’ll do ya.

In my demo site, you’ve no doubt noticed the checkerboard motion banner. Hopefully it was memorable.

Do you know how I did it? 100% CSS.

It’s remarkable what’s possible with CSS3. The sky is the limit. For some inspiration, check out links here and here.

#3: Structured data

The Yoast SEO plugin is bloated and awful (evidence: the existence of this add-on plugin) but they have an excellent structured data write-up I’m going to begrudgingly reference:

Structured data is code in a specific format, written in such a way that search engines understand it. Search engines read the code and use it to display search results in a specific and much richer way.

That’s the “what”. Here’s the “why”: you can leave it to Google to crawl your website and determine what information is important, or you can tell Google yourself what’s important—and with a great deal of specificity.

Enter structured data. There are different ways of going about it. Google recommends JSON-LD, which is contained entirely in a <script> tag. For this client’s one-pager, I used HTML Microdata. Here’s an excerpt:

<div class="col-md-12 col-lg-4" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
	<h2>Address</h2>
	<p>
		<span itemprop="streetAddress">123 Main St</span><br />
		<span itemprop="addressLocality">Anywhere</span>, <span itemprop="addressRegion">CA</span> <span itemprop="postalCode">01234</span><br />
		<span itemprop="addressCountry">United States</span>
	</p>
</div>

What I like about HTML Microdata is that the relevant information I want Google to know is already in the body of the page; it merely needs to be called out. Using itemprop parameters on <span> tags, you can do just that.

I understand that for many people this is a whole new thing to learn. You’re going to have to spend some time at schema.org becoming familiar with the hierarchy and syntax. But once you learn it, writing it will become reflexive. The SEO benefits can’t be overstated.

#4: Comprehensive favicons

If you don’t know much about favicons, I’ll simply say they’re more complicated than they have any right to be. The number of iterations an icon needs to display nicely on every platform… it’s mind-boggling. I’m tempted to research why, but a very large part of me doesn’t want to know.

Instead, allow me to refer you to the RealFaviconGenerator. Go there with a square-shaped image (512×512 is ideal) and dig through all the options that follow.

They’re going to recommend you put these files at the root level of your site. From a housekeeping point of view, that doesn’t sit well with me. You’re more than capable of putting them in a sub-directory—there’s just one consideration. Continue on to #6 to learn about that.

#5: Custom 404 page

If you don’t create your own custom 404 page, your visitors will probably land on a terse Apache “Not Found” message when they visit a non-existing page. On a one page website, perhaps you don’t care. Any visitors who attempt to visit anything other than the only page that exists (the home page) shouldn’t expect better.

But, even for a one-pager, there’s an important reason to create a custom 404 page: you want to keep visitors on your site. If they see that Apache message, they’re going to bounce.

This doesn’t have to be fancy. Among whatever else you want to include, just add a link back to your home page.

As for where to declare the reference to this page, that happens in the .htaccess file. Read on.

#6: Apache rewrites

The .htaccess file lives at the root level of your site. There’s a lot you can do with it. I’m going to give you the entire contents of my file, then we’ll re-group and discuss.

### Set 404 page
ErrorDocument 404 /404.php
 
### Mod rewrite rules
<IfModule mod_rewrite.c>
 
### Start rewrite and set basedir
RewriteEngine on
RewriteBase /
 
### Rewrite without the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
 
### Redirect all requests for favicon.ico to the proper directory
RewriteCond $0 !=favicons/favicon.ico
RewriteRule ^([^/]+/)*favicon\.ico$ /favicons/favicon.ico [R=301,L]
 
### Rewrite without www
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
 
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
 
### Rewrite HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
 
### Rewrite without index.php
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
 
### Rewrite without .php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
 
</IfModule>

First things first: just steal that code outright. Don’t write your own Apache code if you can avoid it; it’s infuriatingly unforgiving. What you see above, I cobbled together piece by piece from countless sources over the years.

You’ll see, at the top, the declaration of the 404.php file as the ErrorDocument. That’s where that happens. Very straightforward.

You’ll also notice, around the middle, a favicon.ico redirect. That file is already referred to in the index.php <head> tag. But what happens when someone visits a file or page that is not the home page? Your browser defaults to looking for it at the root level, whereas I much prefer (as stated in #4 above) to keep the many favicon files in their own folder. Hence, this rule redirects any request to favicon.ico to its actual location in favicon sub-directory.

As for everything else, the main thrust of it is URL conformity. If you don’t rewrite your URLs, your home page can (and will) resolve to all of these:

  • http://www.awesomesite.com
  • http://www.awesomesite.com/
  • https://www.awesomesite.com
  • https://www.awesomesite.com/
  • http://awesomesite.com
  • http://awesomesite.com/
  • https://awesomesite.com
  • https://awesomesite.com/

That isn’t even half of them. And which one will Google index?

What I feel like. GOSH.

This series of rules enforces a rewrite from http to https and www to non-www; removes the trailing slash; removes the index.php file name; and finally, removes the .php extension from any other page. A URL only ever resolves one way.

Trust me: you need to do this.

#7: Sitemap

Related: create a sitemap for your site.

Again, on a one-pager, you might be laughing at the very idea. But what a sitemap does is tell Google what page(s) to index, as opposed to leaving it to Google to figure out. You can either take the lead or be led.

Let’s lead. Let’s have a sitemap that we can submit to Google Search Console.

It’s not hard. Create a sitemap.php file with the following code. Replace the URL with your own.

<?php
header("Content-type: text/xml; charset=utf-8");
 
//create your XML document, using the namespaces
$urlset = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" />');
 
// create homepage
$url = $urlset->addChild('url');
$url->addChild('loc', 'https://company.com');
$url->addChild('changefreq', 'monthly');
$url->addChild('priority', '1.0');
 
// add whitespaces to xml output (optional)
$dom = new DomDocument();
$dom->loadXML($urlset->asXML());
$dom->formatOutput = true;
 
// output xml
echo $dom->saveXML();
?>

#8: Google Analytics

You need at least a basic amount of data regarding site visitors, even on the simplest of websites.

Sign up at Google Analytics. Register your website. Plug your unique tracking code into the following code block, inserted at the top of your <head> tag:

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX-X"></script>
<script>
	window.dataLayer = window.dataLayer || [];
	function gtag(){dataLayer.push(arguments);}
	gtag('js', new Date());
	gtag('config', 'UA-XXXXXXXXX-X');
</script>

In Memoriam

I hope these eight tips were useful. If you follow them, your custom one-pager will be on solid footing.

Also feel free to just use my template. A little customization of content and color palette, and you can quickly make it your own.

Submit a comment

Your email address will not be published. Required fields are marked *