diff --git a/.gitignore b/.gitignore
index 9168178..ce63e47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-events
-mo
\ No newline at end of file
+venv
+dist
\ No newline at end of file
diff --git a/README.md b/README.md
index cbb424f..445b5d3 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,72 @@
-# Klank docs
+# README.md
-## installation
-Run the install.sh to install [Mustache](https://github.com/tests-always-included/mo)
+### Installation
+Create a virtual python environment using ` python -m venv venv`
+Activate the virtual environment using `source venv/bin/activate`
+Install the packages using `pip install -r requirements.txt`
-Also, pandoc is needed. Additionally researching this thing https://github.com/pandoc-ext/include-files/tree/main
+### Running
+Compile the content into a static site using
+```
+python app.py
+```
+
+This creates the "dist" directory, with all of the HTML in there.
+At the moment, `dist` is part of the `.gitignore`!
-More info to come ;)
+### Writing Content
+Within the `content` directory, you can create/edit markdown files. When compiling the markdown content, `app.py` will look for jinja templates in the `templates` directory. If the markdown file is in the root of `content`, it will try to load a template with the same filename as the markdown file. For instance, `about.md` will look for `about.jinja`.
+If the markdown file is in a subdirectory, it will look for a template with the same name as the subdirectory. At the moment, there is no functionality for deep nested folders. So, `recipes/tomato-soup.md` wants `recipes.jinja`. If the template does not exist, the default template is `post.jinja`.
-## Scripts & folders
+The project uses [Jinja](https://jinja.palletsprojects.com/), which allows for extending templates, using variables, looping trough variables, and other funky features!
-- `newsletters` write your new newsletter here
-- `templates` contains a markdown template for events, that are being grabbed via
-- `get_events.sh` run as `sh get_events.sh` to grab all events from the klankschool calendar and store them as markdwon files
-- `install.sh` the installation script for Mustache
-- `make_newsletter.sh` run as `sh make_newsletter` to translate all created newsletters in the `newsletters` directory into HTML. Created newsletters are stored in the `dist` directory
+Additionally, `component-inventory.csv` is loaded as a dataset.
+
+### Transclusion
+You'll be able to transclude one markdown file into another, by applying the following syntax:
+
+```MARKDOWN
+{! path-to-file.md !}
+```
+
+The transclusion package also allows for transcluding specific lines:
+
+```MARKDOWN
+{! path-to-file.md!lines=1 3 8-10 2}
+```
+In the example above, it would read the file and include the lines 1, 3, 8, 9, 10, 2.
+
+
+
+
+### Metadata
+Metadata can be applied to markdown files using FrontMatters YAML. The metadata is accessable in the jinja tempaltes using `page.{metadata}`. In the example below, this could be, `page.title`.
+
+```MARKDOWN
+---
+excerpt: tl;dr
+title: Capacitors
+type: Capacitor
+valueSymbol: unf
+description: This is the description
+---
+```
+
+
+### Assets
+At the moment, the `src/assets` directory is copied to the `dist` folder, to apply CSS.
+
+
+### TODO
+- [ ] update readme
+- [ ] fix issue with YAML data showing up in included files
+- [ ] lurk newsletter?
+- [ ] minify/gzip the HTML
+- [ ] Export to PDF
+- [ ] Export to mediawiki
+- [ ] Export to PDF with zine layout
+- [ ] last edited date
+- [ ] Direct link to the markdown file in git?
+- [ ] Markdown page breaks
\ No newline at end of file
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..aa6f3ad
--- /dev/null
+++ b/app.py
@@ -0,0 +1,115 @@
+import os
+from pathlib import Path
+import shutil
+import csv
+
+from jinja2 import Environment, PackageLoader, select_autoescape
+import frontmatter
+import markdown
+from markdown_include.include import MarkdownInclude
+from slugify import slugify
+
+markdown_include = MarkdownInclude(
+ configs={'base_path': 'src/content/'}
+)
+
+env = Environment(
+ loader=PackageLoader("src"),
+ autoescape=select_autoescape()
+)
+
+CONTENT_D = os.path.abspath("src/content")
+OUTPUT_D = "dist"
+documents = {}
+
+def slugify_filter(value):
+ return slugify(value)
+
+env.filters["slugify"] = slugify_filter
+
+
+def render_single_file(template, page, path, dist):
+ html = template.render(documents=documents, page=page)
+ name = Path(path).stem
+
+ if not os.path.exists(dist):
+ os.makedirs(dist)
+
+ with open(f"{dist}/{name}.html", "w", encoding="utf-8") as output_file:
+ output_file.write(html)
+
+
+def get_page_data(path):
+ filename = Path(path).stem
+ page = frontmatter.load(path)
+ page['slug'] = slugify(filename)
+ page.body = markdown.markdown(page.content, extensions=['def_list', 'footnotes', markdown_include])
+
+ return page
+
+
+def render_posts(path):
+ name = Path(path).stem
+ print(f"looking for {name}.jinja")
+ template = env.select_template([f"{name}.jinja", "post.jinja"])
+
+ for filename in os.listdir(path):
+ if filename.endswith(".md"):
+ post_path = os.path.join(path, filename)
+ page = get_page_data(post_path)
+ render_single_file(template, page, post_path, f"{OUTPUT_D}/{name}")
+
+
+def preload_documents():
+ print("preload any needed data")
+
+ for subdir in os.listdir(CONTENT_D):
+ path = os.path.join(CONTENT_D, subdir)
+
+ if os.path.isdir(path):
+ name = Path(path).stem
+ if name not in documents:
+ documents[name] = []
+ for filename in os.listdir(path):
+ if filename.endswith(".md"):
+ post_path = os.path.join(path, filename)
+
+ documents[name].append(get_page_data(post_path))
+
+ elif Path(path).suffix == '.md':
+ documents[Path(path).stem] = get_page_data(path)
+
+def copy_assets():
+ if os.path.exists("dist/assets"):
+ shutil.rmtree("dist/assets")
+
+ shutil.copytree("src/assets", "dist/assets")
+
+def get_inventory():
+
+ with open("src/content/component-inventory.csv") as f:
+ documents['inventory'] = []
+ for line in csv.DictReader(f, fieldnames=('ID', 'Name', 'Value', 'Type', 'Date', 'Where')):
+ documents['inventory'].append(line)
+
+def main():
+ get_inventory()
+ preload_documents()
+
+ print("render the content")
+ for subdir in os.listdir(CONTENT_D):
+ path = os.path.join(CONTENT_D, subdir)
+
+ if os.path.isdir(path):
+ render_posts(path)
+ elif Path(path).suffix == '.md':
+ template = env.select_template(
+ [f"{Path(path).stem}.jinja", "post.jinja"])
+ page = get_page_data(path)
+ render_single_file(template, page, path, OUTPUT_D)
+ else:
+ print("i cannot handle this file yet")
+
+ copy_assets()
+
+main()
diff --git a/dist/newsletters/december.md.html b/dist/newsletters/december.md.html
deleted file mode 100644
index 404c568..0000000
--- a/dist/newsletters/december.md.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
+
+{% else %}
+No components were identified yet
+{% endif %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/templates/index.jinja b/src/templates/index.jinja
new file mode 100644
index 0000000..2bea713
--- /dev/null
+++ b/src/templates/index.jinja
@@ -0,0 +1,6 @@
+{% extends "base.jinja" %}
+
+{% block content %}
+
This is the index
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/templates/post.jinja b/src/templates/post.jinja
new file mode 100644
index 0000000..e2e2009
--- /dev/null
+++ b/src/templates/post.jinja
@@ -0,0 +1,11 @@
+{% extends "base.jinja" %}
+
+{% block content %}
+
template: post.jinja
+
+
+
+
{{page['title']}}
+ {{ page['body'] }}
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/event.md b/templates/event.md
deleted file mode 100644
index caac345..0000000
--- a/templates/event.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# {{TITLE}}
-This event starts at {{START_DATETIME}}
\ No newline at end of file