diff --git a/README.md b/README.md
index 2c7b8e3..a548627 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,10 @@
+
+
+
+
+
+
+
# logseq-cli
[](https://github.com/muellerei/logseq-cli/actions/workflows/tests.yml)
diff --git a/docs/images/banner-dark.svg b/docs/images/banner-dark.svg
new file mode 100644
index 0000000..d5f5141
--- /dev/null
+++ b/docs/images/banner-dark.svg
@@ -0,0 +1,26 @@
+
diff --git a/docs/images/banner-light.svg b/docs/images/banner-light.svg
new file mode 100644
index 0000000..6224a74
--- /dev/null
+++ b/docs/images/banner-light.svg
@@ -0,0 +1,26 @@
+
diff --git a/docs/images/social-preview.png b/docs/images/social-preview.png
new file mode 100644
index 0000000..ac04a2f
Binary files /dev/null and b/docs/images/social-preview.png differ
diff --git a/docs/images/social-preview.svg b/docs/images/social-preview.svg
new file mode 100644
index 0000000..9784c8f
--- /dev/null
+++ b/docs/images/social-preview.svg
@@ -0,0 +1,26 @@
+
diff --git a/docs/src/banner.py b/docs/src/banner.py
new file mode 100644
index 0000000..224bc25
--- /dev/null
+++ b/docs/src/banner.py
@@ -0,0 +1,67 @@
+# Writes docs/images/banner-light.svg and banner-dark.svg (1280x320). With --social, writes social-preview.svg
+# instead (the picture behind docs/images/social-preview.png; render it to 1280x640 PNG).
+# Run: python3 docs/src/banner.py [output directory] [--social]
+import os
+import sys
+args = [a for a in sys.argv[1:] if a != '--social']
+OUT = args[0] if args else os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'images')
+SOCIAL = '--social' in sys.argv
+T = {
+ 'light': dict(bg1='#ffffff', bg2='#eef3fb', dot='#0d1117', dota='0.07', panel='#ffffff', stroke='#c3ccd6', rule='#e1e6ec',
+ title='#1f2328', sub='#31363d', small='#59636e', text='#1f2328', dim='#59636e',
+ accent='#0b7a75', failed='#cf222e'),
+ 'dark': dict(bg1='#0d1117', bg2='#161b22', dot='#ffffff', dota='0.06', panel='#161b22', stroke='#30363d', rule='#30363d',
+ title='#e6edf3', sub='#c9d1d9', small='#8b949e', text='#e6edf3', dim='#8b949e',
+ accent='#2ec4b6', failed='#f85149'),
+}
+def page(c, px, top, pitch, f, right):
+ """A Logseq page as an outline: f scales offsets and font sizes, right is the x the status tags end at."""
+ bx, tx = px + 34 * f, px + 54 * f
+ y = [top + i * pitch for i in range(4)]
+ caret_x = tx + 33 * 0.6 * 19 * f # after "Call with Alex about the contract"
+ return f'''
+ ## Log
+
+
+ Call with Alex about the contract
+
+ ✕ refused
+
+ 14:31 Decided to ship on Friday
+ ✓ written
+ confirmed with Logseq · the block you type in stays yours'''
+def svg(theme, social):
+ c = T[theme]
+ w, h = (1280, 640) if social else (1280, 320)
+ r = 0 if social else 24
+ head = f'''\n'
+if SOCIAL:
+ open(os.path.join(OUT, 'social-preview.svg'), 'w', encoding='utf-8').write(svg('dark', True))
+else:
+ for th in T:
+ open(os.path.join(OUT, f'banner-{th}.svg'), 'w', encoding='utf-8').write(svg(th, False))