So you want to hand-code your own ebook?

It's fiddly but fun and I will show you how.

Hand coding an ebook in ePub 3 is satisfying and will make a clean package, free from legacy bits from previous versions of the specification. You will need some experience of coding valid HTML5.

What is ePub?

ePub is a series of well-formed HTML documents in a compressed package, with an XML document sort of sitting outside it, telling the ebook reader what is inside. Like when you get a Christmas present from abroad but the customs label ruins the surprise. These are the minimum files you need. (I experimented by taking out different files so you don't have to!)

Drawing of a present with 'socks' written on the label

My fingers are ready. What do I do?

Step One
Write your novel.

You want a character who starts off wanting something, but needs something else. Have her leave her comfort zone, spatially or mentally, face her antagonist - whether that's a person or a situation - then eventually meet a choice between getting what she wants and pursuing what she needs. She must choose what she needs. This is an emotional peak of your book. She returns home, with a little bit of her changed forever. This is all in Into The Woods by John Yorke.

Step Two
Make a new folder called 'awesomenovel', then one in it called 'META-INF', then some text files with a text editor (TextEdit or Notepad). Rename them with the names above. Make sure you really are changing the file extensions. MacOS might give you the impression that you are doing this but you are not: Finder Preferences > Advanced > 'Show all filename extensions'.
Step Three
Fill in your files as below:

container.xml

<?xml version="1.0" encoding="UTF-8"?>

<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
   <rootfiles>
      <rootfile full-path="package.opf"
      media-type="application/oebps-package+xml" />	
   </rootfiles>
</container>

There you go. Stick that in.

maintext.xhtml

Make one of these per chapter. You don't have to number the filenames, you can specify the order later in the package document. Use this template:

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE html>

<html lang="en"
   xmlns="http://www.w3.org/1999/xhtml">

   <head>
      <title>Chapter title</title>
      <link rel="stylesheet" type="text/css" href="stylesheet.css"/>
   </head>

   <body>
      <h1>Chapter title</h1>
      <p>Your amazing prose.</p>

   </body>
</html>
Drawing of a child lying on the floor writing with a pencil

nav.xhtml

This template is much the same as the main text one, above. It's your contents page so you can probably put a publishers imprint here or dedications. Each chapter is a link to the chapter file.

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE html>
        
<html	lang="en"
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:epub="http://www.idpf.org/2007/ops">
        
   <head>
      <title>Awesome Novel</title>
   </head>
        
   <body>
        
      <nav epub:type="toc">
         <h1>Awesome Novel</h1>
        
         <ol>
            <li><a href="intothe.xhtml">Into the</a></li>
            <li><a href="woods.xhtml">Woods</a></li>
            <li><a href="backagain.xhtml">Back again</a></li>
         </ol>

      </nav>
        
   </body>
</html>

package.opf

Paste this in:

<?xml version="1.0" encoding="UTF-8"?>

<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="id">

   <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:identifier id="id">123456789</dc:identifier>
      <dc:title>Awesome Novel</dc:title>
      <dc:language>en</dc:language>
   <meta property="dcterms:modified">2021-01-01T00:00:00Z</meta>
   </metadata>

   <manifest>
      <item href="nav.xhtml" id="nav" media-type="application/xhtml+xml" properties="nav"/>
      <item href="backagain.xhtml" id="ch3" media-type="text/html"/>
      <item href="intothe.xhtml" id="ch1" media-type="text/html"/>
      <item href="woods.xhtml" id="ch2" media-type="text/html"/>
   </manifest>

   <spine>
      <itemref idref="nav"/>
      <itemref idref="ch1"/>
      <itemref idref="ch2"/>
      <itemref idref="ch3"/>
   </spine>

</package>

These are the minimum metadata to make it work - I tested. The identifier ID can be any number. When you revise your file, update the modified date, or your e-reader won't realise it's changed.

Your manifest must contain every file of interest, including images and style sheet, if you have one. I put my chapters in alphabetical order because that's how they appear in Finder / Windows Explorer. Each gets assigned a unique ID. 'Spine' tells the e-reader the expected sequence.

What about the Style Sheet?

If you've been following you will have put a link to a style sheet in every chapter, even though we haven't created one. You can do that - create a file called stylesheet.css and place it in the main folder with the rest of your files, add it to your manifest - but many e-readers will make your novel look beautiful anyway.

Don't budge a cook by its lover

Your book cover: Create your cover-image in your favourite image editing programme then save it in your main folder. Add a link in your manifest with id="cover" media-type="image/jpg" or whatever image format you used. That's all you need to do!

HTML5 tricks

I tested iBooks and some interesting HTML5 tags still work: <mark> highlights text in yellow, like this, which is pretty nice.

<details> is a 'press to reveal' hidden-answer. There is one in Step One, above. Did you spot it? A little triangle indicates it is there, which you may not think enough. You could explicity add 'click to reveal'.

<abbr title="this is what this acronym means"> will work but iBooks makes no indication it is there to be hovered over. Even without the title attribute it might help screen readers know that acronyms are to be spelled out instead of pronounced.

Drawing of someone holding their book called 'Awesome Novel - by Me'

OK I've written it. What now?

Great. Test your xhtml files are valid using a validator. Safari is quite good at spotting errors if you just try opening them in that.

To compress your folder the correct way, download eCanCrusher. On the Mac at least, it sits in a folder and you drop your ebook folder on top of it. Your ePub book appears.

To validate your ePub, download EPUBCheck. This runs in Command line / Terminal. Put your epub file in the same folder as EPUBCheck and type:

        >  java -jar epubcheck.jar awesomenovel.epub

It's all in the README.txt.

Finally, double-click on your e-book and your system's e-reader should open it. Send it to your phone and try it there. Nice job!