Yet another Gemini publishing framework with HTML and Atom support, written in Bash and Sugar-C

04d3241 Fix permissions

5 months ago

8f1e547 Fix

5 months ago


standard-readme compliant license MIT

GemPress is a framework to streamline publishing a Gemini Capsule, while also making it available as a common static website, for a broader audience.

At it's core, there's a simple gemini-to-html tool, as well as an atom feed generator, both of which written in C but intended to be executed as scripts using Sugar-C.

Sugar-C is a tcc flavour (fork), that compiles C code on the fly 'as if' a scripting language out of the box and leans on <sugar.h> library for doing simple text file procedures.

The code should be easy enough for others to customize to their needs, and contributions are also welcome. Some effort was put into trying to keep it simple and well documented.

#Table of Contents


Install Sugar-C from the GitHub repository, like:

git clone https://github.com/antonioprates/sugar.git
cd sugar

Note: you might have to use sudo ./install.sh depending on your user permissions.

Alternative: use another C compiler see alternative setup section.

Then, just clone this repo:

git clone https://git.sr.ht/~aprates/gempress

Done, you should be good to go!


#Format conversion

These are the standard markup conversions currently supported by gmi-to-html (the core tool):

  • ", &, <, >, html escaped codes
  • => internal links, converts path to *.html
  • => external links, keeps original URL
  • # heading, also sets the page title
  • ## sub-heading
  • ### sub-sub-heading
  • * list item
  • > blockquote
  • pre-formatted block enclosed in triple backtick (```)

See Solderpunk's Gemini Specifications, section 5 for text/gemini media type reference.

GemPress offers 2 extra markup conversions (non-standard for Gemini), but those need to be explicitly enabled via configuration flag:

  • --- horizontal rule
  • inline code enclosed in backtick (`) - see limitations section


You can automatically append gemini contents on all your pages. See gmi-footer.gmi and web-footer.gmi files under template folder.


There is a simple style.css included under template folder. Out of the box, it is provided as a dark-blue theme, but can be edited to tweak the outputted website look and feel.


Also, there is a space capsule icon sample, designed by smalllikeart and made freely available from flaticon, converted with favicon.io.

#How to use?

#New Capsule Wizard

You can create a capsule folder structure with a capsule.conf auto-magically by using the wizard script, for example:

./new-capsule ~/capsule

The wizard will ask for:

  1. your name (author)
  2. the name of the capsule
  3. the capsule's url, i.e.: user.srht.site
  4. the srht OAuth token

About the OAuth token see publish with SourceHut section. You may jump directly to ./publish auto if you have answered all the wizard's four questions, and have your page online.

#Manual Setup

From the project root create a copy of capsule-example.conf as capsule.conf and edit the parameters accordingly.

cp capsule-example.conf capsule.conf
nano capsule.conf

Note: you can copy the template folder elsewhere and customize it or just set directly to the template folder provided with this project.

Your configured contents localBaseDir is expected to have the following structure:

├── index.gmi      # Home
└── log
    ├── index.gmi  # Archive (links to the posts)
    └── YYYY-DD-MM-post-1.gmi

Also, your configured templateDir should be of the following structure:

├── gmi-footer.gmi # Appends to Gemini Capsule only
├── web-footer.gmi # Appends to Website only
├── favicon.ico
└── styles.css

The publish script adds the first 5 links of the Capsule Archive to your Capsule Home, then the footer is appended afterwards. So your Home should end with something like:

## Capsule Feed
Here are my most recent posts:

For the publish action there are currently two modes supported.


to local


./publish local

Then, you get your Capsule built at ./capsule and a HTML Website clone under ./website folder.

Note: the script will overwrite ./website folder, so it's not recommended to edit HTML output. Rather the best solution would be to tweak the scripts.

You can also clean up those folders with:

./publish clean


to SourceHut

Finally, there is a CI-like (lol) script to publish to SourceHut Pages directly. Navigate to gemini://srht.site for the information on how to get hosted on SourceHut.

Edit the capsule.conf to add your srhtToken and srhtSendUrl configurations.

Once all is set, provided you have already done publish local, run:

./publish srht

You can also build local files + publish to srht + clean in one step:

./publish auto

That's it!


Patches and questions? Send to my public inbox: ~aprates/public-inbox@lists.sr.ht

#Technical notes

For clarity, here INDEX means log/index.gmi, the Archive's index, of which the feed is generated, and not the file on the root dir (Home).

The following steps describe the main publish local process:

website steps

  1. take a clean copy of localBaseDir to ./capsule
  2. append INDEX first 5 links to Home
  3. generate https atom feed from INDEX
  4. append web-footer.gmi to all files, except INDEX
  5. append back-to-Home-link to INDEX
  6. convert ALL gmi files to html into ./website dir

gemini steps

  1. take a clean copy of localBaseDir to ./capsule
  2. append INDEX first 5 links to Home
  3. generate gemini atom feed from INDEX
  4. append gmi-footer.gmi to all files, except INDEX
  5. append back-to-Home-link to INDEX

Note that, you should end up with two folders ./website and ./capsule ready to be published.

Also note that, the included atom feed generator is a bit of a primitive tool and it expects the Archive's log/index.gmi file to contain the list of links (=>), like:

=> /log/some-title.gmi YYYY-MM-DD Heading Of The Post

See the Gemini simple feed specification for /log/index.gmi structure reference. Make sure that the URLs contain the date as the initial part of the description, as date is extracted from there. You may add normal gemini contents above, below or in-between, as any content not in that exact format will be ignored. The generator only cares about the links with description starting as YYYY-MM-DD when building the feed.


#Inline formatting shortcomings

Unless backtick is the first or last character on the line, inline formatting of code expects a blank space before the opening markup and a blank space after the closing. And this might not be the expected behavior for most people used to markdown text, therefore you CAN'T pre-pend or append those immediately with punctuation .,:;!?.

Yet this helps to keep a straightforward and clean implementation. When writing your markdown, you can overcome this shortcoming of the underlying gemini-to-html tool by simply adding an extra blank space where needed.

There is also a tag bleeding risk if you forget to close your backticks. The tool does a futile attempt to prevent the bleeding, by checking if the number of backticks is even in each line. But this provides no real guarantee that the code tag won't bleed on the html source. You could check outputted HTML for validity if you are a bit paranoid, after each time you edit.

I might add config support for this feature in the future, but for now, if you want to turn it off, just comment out the inline code implementation on the lineToHTML function in case this is causing you any troubles.

#Alternative setup

You should be able to skip Sugar-C install if you prefer, but you will need to build the core tools from the C sources using whatever C compiler you have or prefer, by including sugar.h to this project.

Note: the bash scripts, internally calls Sugar-C to run the C scripts, so it assumes you have Sugar-C configured in your system. If not, you will have to manually update the bash scripts.

After compiling all .c sources, update bash scripts to use the binaries instead of C scripting where applicable, like, for example:

< sugar src/gmi-to-html.c $filePaths
> bin/gmi-to-html $filePaths


MIT License