Manually creating epub from scratch (With template)
Posted on 2024-06-29
The why
I needed to create an ebook in epub format in Japanese. First issue I had was not being able to display the text vertically. I tried to use LibreOffice export to epub option, tried to use Calibre to mess around with options, I tried to look through the exported epub to try and change some stuff. Nothing worked. I am sure there is a way to do it through these software but I was not able to find a way to make it work. Second issue I had was the layout was messed up even in horizontal mode. There were weird inconsistencies and gaps between paragraphs or re-flow issues. By then, I had wasted enough time and decided to create epub from scratch.
Not sure if it exists now but there was no complete guide to creating an epub from scratch when I did my epub (especially for epub 3.3). Here is my attempt at it. You can also find the template on GitLab and GitHub.
The how
epub format is just a regular zip file but with a different extension. You can change the extension to zip and extract it to see the contents. It contains some meta information files that ebook readers use to know how to put all the files together to display it on screen. Rest of the files are content files such as text, images, videos, audios etc. Just like a website.
Inside, you will find that there are some files and folders. The basic structure of epub is shown below.
. ├── META-INF │ └── container.xml ├── mimetype └── OEBPS ├── content.opf ├── images │ └── cover.jpg ├── styles │ └── stylesheet.css └── text ├── text2.xhtml ├── text3.xhtml ├── text.xhtml └── nav.xhtml
META-INF
In this folder, there is a file called container.xml. This defines the location of content.opf . You may change the name of the content folder (in this case OEBPS) to something else and this must be changed in the container.xml file. You may have more information and files in this folder but container.xml is required.
Here is an example of container.xml.
<?xml version='1.0' encoding='utf-8'?> <container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0"> <rootfiles> <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/> </rootfiles> </container>
mimetype
This defines that this file is an epub file.
Here is the content.
application/epub+zip
OEBPS
As stated in the META_INF section, you can change the name of the folder if you wish. The most important file in this folder is content.opf. This defines the location and order of the content to be displayed. You can also define certain metadata.
content.ops
Here is an example content.opf
<?xml version="1.0" encoding="UTF-8"?> <package xmlns="http://www.idpf.org/2007/opf" unique-identifier="unique-identifier" version="3.0"> <metadata xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:opf="http://www.idpf.org/2007/opf"> <dc:identifier id="unique-identifier">b62482e5-6a3a-4f4c-b73a-ee3292ff8068</dc:identifier> <dc:title>Title</dc:title> <dc:language>en</dc:language> <meta property="dcterms:modified">2024-04-27T13:00:00Z</meta> <dc:creator id="creator">Creator Name</dc:creator> <meta refines="#creator" property="role" scheme="marc:relators" id="role">aut</meta> <meta refines="#creator" property="alternate-script" xml:lang="ja">Creator Name</meta> <meta refines="#creator" property="file-as">Name, Creator</meta> </metadata> <manifest> <item id="cover" href="./images/cover.jpg" properties="cover-image" media-type="image/jpeg"/> <item id="text" href="./text/text.xhtml" media-type="application/xhtml+xml"/> <item id="text2" href="./text/text2.xhtml" properties="nav" media-type="application/xhtml+xml"/> <item id="text3" href="./text/text3.xhtml" properties="nav" media-type="application/xhtml+xml"/> <item id="nav" href="./text/nav.xhtml" properties="nav" media-type="application/xhtml+xml"/> <item id="css" href="./styles/stylesheet.css" media-type="text/css"/> </manifest> <spine page-progression-direction="rtl"> <itemref idref="nav"/> <itemref idref="text"/> <itemref idref="text2"/> <itemref idref="text3"/> </spine> </package>
You will need to change identifier, title, language etc. In the manifest section, you will need to specify anything that will be included in the book. Even if they are not text pages. For example, images, videos and audios will need to go here. Spine section is where you specify the order of things. Mostly pages. Anything included here will be visible as a page. So in this case, if you don’t want table of contents, then you can remove it here and it won’t show up as a page. However, it will still be shown in the ebook reader as table of contents.
Stylesheet
This is a standard css file. You can change the layout and the way your contents are displayed.
Example.
@page { margin: 5px 5px 5px 5px } body { writing-mode: vertical-rl } .upright-text { text-orientation: upright } .center-text { text-align: center } .horizontal-text { writing-mode: horizontal-tb }
The content file
This is where your content lives.
<?xml version='1.0' encoding='utf-8'?> <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'> <head> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/> <link href='../styles/stylesheet.css' rel='stylesheet' type='text/css'/> <title>TITLE</title> </head> <body> <div class="center-text horizontal-text"> <h2>HEADER</h2> </div> <p>Some text here</p> <p>You can also use<br /> breaks</p> </body> </html>
Zipping the folder
You need to zip the folder in a way that it becomes a valid epub file.
I found the following command to work well.
To create the zip and add the mimetype file.
zip -0Xq book.epub mimetype
To add rest of the files to that zip. Excluding mimetype file.
zip -Xr9Dq book.epub * -x mimetype
These two commands should be run in the root directory of the book.
Resources
The most useful resource is the latest epub spec.
And my epub from scratch template.
Conclusion
You should now be able to create epub from scratch. And have complete control over your ebook.
Want to help?
You can share it! This website disallow all bots from crawling and indexing so without your help, no one would discover this website.