A poor attempt at making a static blogging engine in Typescript
First public commit


browse  log 



You can also use your local clone with git send-email.


A poor attempt at making a static blogging engine in Typescript.


This is garbage software, the README is unreadable, and I will remake the whole README at another time.

Also, something something alpha software something something will change without warning something.


Probably only works on Linux.

> node -v
> npm ls
engrafi@0.0.1 /home/denise/blog
├── @types/jsdom@21.1.6
├── @types/marked@6.0.0
├── @types/node@20.10.4
├── country-code-emoji@2.3.0
├── esbuild@0.19.9
├── esthetic@0.6.4-beta.1
├── jsdom@23.0.1
├── marked@11.0.1
├── postject@1.0.0-alpha.6
└── typescript@5.3.3

#How things are split

Everything is either an article, a section, a header or a footer.

Articles are things written by authors, with dates, and titles.

An article has a Markdown page to go along with it necessarily, with some special syntax.

Sections are things that were written. We don't care about the dates nor the authors.

A section can be a link to somewhere that will show up on the section list under the header. It does not necessarily need a Markdown page to go along with it.

The header and the footer is defined in the main configuration and will appear on every rendered page.

You can set a preferred section, which will act as a home page / main page. In this case, the latest article will be prepended to the section content.

#How to use

#How to compile

Run npm run build or npx tsc.

A ./dist folder should appear.

#How to configure

#General configuration

Create a general configuration in ./dist.

This will serve as the place on which you will define:

  • the blog name;

  • the blog description;

  • the blog domain;

  • the default general language;

  • the relative paths for the sections and the articles;

  • the default section title, which is case sensitive (home page);

  • the blog footer;

  • whether or not you want rss;

  • whether or not you want the archives;

RSS and archives appear as sections on the section bar.

For example:

    "header": {
        "title": "~denise",
        "description": "Adminsys, queeritude et plus"
    "sectionsPath": "./sections",
    "postsPath": "./posts",
    "language": "fr",
    "domain": "https://blog.simplydenise.eu",
    "defaultSection": "page principale",
    "footer": "<p>This blog is generated by <a href='https://git.sr.ht/~denisebitca/engrafi'>~denisebitca/engrafi</a>, AGPLv3. All content is <a href='https://creativecommons.org/licenses/by-sa/4.0/'>CC BY-SA 4.0</a> except if specified otherwise</p>",
    "rss": true,
    "archives": true
#Section configuration

A section resides in ./sections by default and looks like this.

    "url": "/index.html",
    "title": "page principale",
    "contentPath": "markdown/main.md"

the URL is relative to the domain, the title is case sensitive (if you want to make the section a default section), and the content path is relative to the sections folder.

The markdown file is a regular Markdown file that is supported by the Marked parser.

For example:

## contacts

- fediverse: <a rel="me" href="https://potate.space/@denise">@denise@potate.space</a>
- matrix: @denise:envs.net

All sections are added to the links under the header. There is no way of preventing this behaviour for now.

#Article configuration

Articles come in two files: the article metadata which points to the article content.

Both these files reside within ./posts.

The article metadata looks like this:

    "title": "Et c'est reparti pour encore un changement !",
    "date": "December 12 2023",
    "author": "Denise",
    "language": "fr",
    "description": "Nouveau logiciel, nouvelle année ?",
    "contentPath": "markdown/nouveau_logiciel.md"

And the article content can look like this:

Le blog a changé légèrement. Pour l'instant, je ne dévoile pas le code qui a méné à ce changement, mais je peux vous donner des détails :

- Il n'y presque plus de templates en HTML pur

- Tout est du markdown presque

- C'est conçu pour être utilisé par plus de gens que moi

:::::en- I can set the lang attribute per paragraph

Paragraphs can be set to specific languages by prefixing :::::[ISO 639-1 language code].

Currently, the supported languages are "en" | "fr" | "pt" | "de" | "ro" | "es".

#How to build

#If you want the binary
> npm run build
#If you want the bundled code
> npm run buildCode

#How to run

Assuming you have the following directory tree:

├── posts
├── sections

and that in the directory there is a config.json and a strings.json,

> engrafi config.json

All the content will be generated within ./public. No JS included, it's all HTML and one XML file.

By default, the program is quiet (except for errors). You can set debug output with environment variable DEBUG (0 for no, 1 for yes) and set up a special benchmark with environment variable BENCHMARK (0 for no, 1 for yes).

#How to deploy

Here's an idea:

  • get the latest binary release
  • copy the binary into the working directory
  • have a separate repository with the following tree:
    (your images)
        (your article markdown files)
    (your article metadata files)
        (your section markdown files)
    (your section metadata files)
strings.json (if localised)
  • clone the repository into working directory
  • ./engrafi config.json
  • cp -r images public
  • cp style.css public
  • tar compress the public folder and push it to your preferred page


You can localise the software by modifying "strings.json". Some strings (not marked as debug or fails) will appear on the website.


AGPLv3. Check "LICENSE" for more details.