diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 85c9c65..58ffb69 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -20,6 +20,7 @@ jobs:
run: |
cd bin
make
+ python make-redirects.py
- name: add custom domain
run: echo "lipu-sona.pona.la" > public/CNAME
- name: deploy
diff --git a/bin/make-redirects.py b/bin/make-redirects.py
new file mode 100644
index 0000000..8a4d75a
--- /dev/null
+++ b/bin/make-redirects.py
@@ -0,0 +1,30 @@
+import csv
+from pathlib import Path
+
+OUTDIR = Path("../public/")
+OUTDIR.mkdir(exist_ok=True)
+REDIRECTS = Path("../templates/redirects.csv")
+TEMPLATE = """
+
+ lipu sona pona | Redirect
+
+
+
+ Redirecting...
+
+"""
+
+def redirects():
+ with open(REDIRECTS) as f:
+ reader = csv.reader(f)
+ next(reader) # skip header
+ for line in reader:
+ if not line:
+ continue
+ dest, origin = line
+ yield origin, dest
+
+
+for origin, dest in redirects():
+ with open(OUTDIR / origin, "w") as f:
+ f.write(TEMPLATE.format(dest).strip())
diff --git a/templates/redirects.csv b/templates/redirects.csv
new file mode 100644
index 0000000..e5d9a0a
--- /dev/null
+++ b/templates/redirects.csv
@@ -0,0 +1,176 @@
+redirect_destination,redirect_origin
+
+credits/,credits.html
+license/,license.html
+nimi_pi_pu_ala/,nimi_pi_pu_ala.html
+personal_style/,personal_style.html
+
+lentan/art_revolution/,art_revolution.html
+lentan/chess/,chess.html
+lentan/city_names/,city_names.html
+lentan/game_patches/,game_patches.html
+lentan/game_patches_jp/,game_patches_jp.html
+lentan/jan_lawa_pi_linja_ilo/,jan_lawa_pi_linja_ilo.html
+lentan/keyboard/,keyboard.html
+lentan/la_espero/,la_espero.html
+lentan/nasin_juni/,nasin_juni.html
+lentan/nasin_tenpo/,nasin_tenpo.html
+lentan/o_lawa_e_sona_sina/,o_lawa_e_sona_sina.html
+lentan/phonetic_alphabet/,phonetic_alphabet.html
+lentan/riichi_mahjong/,riichi_mahjong.html
+lentan/shogi/,shogi.html
+lentan/sitelen_pona_ibus/,sitelen_pona_ibus.html
+lentan/supalape/,supalape.html
+
+de/,de_index.html
+de/0/,de_0.html
+de/1/,de_1.html
+de/2/,de_2.html
+de/3/,de_3.html
+de/4/,de_4.html
+de/5/,de_5.html
+de/6/,de_6.html
+de/7/,de_7.html
+de/7a/,de_7a.html
+de/8/,de_8.html
+de/9/,de_9.html
+de/10/,de_10.html
+de/11/,de_11.html
+de/12/,de_12.html
+de/13/,de_13.html
+de/x1/,de_x1.html
+de/x2/,de_x2.html
+de/answers/,de_answers.html
+de/dictionary/,de_dictionary.html
+de/sitelen_pona/,de_sitelen_pona.html
+
+en/0/,0.html
+en/1/,1.html
+en/2/,2.html
+en/3/,3.html
+en/4/,4.html
+en/5/,5.html
+en/6/,6.html
+en/7/,7.html
+en/7a/,7a.html
+en/8/,8.html
+en/9/,9.html
+en/10/,10.html
+en/11/,11.html
+en/12/,12.html
+en/13/,13.html
+en/x1/,x1.htm
+en/x2/,x2.html
+en/answers/,answers.html
+en/dictionary/,dictionary.html
+en/sitelen_pona/,sitelen_pona.html
+
+eo/,eo_index.html
+eo/0/,eo_0.html
+eo/1/,eo_1.html
+eo/2/,eo_2.html
+eo/3/,eo_3.html
+eo/4/,eo_4.html
+eo/5/,eo_5.html
+eo/6/,eo_6.html
+eo/7/,eo_7.html
+eo/7a/,eo_7a.html
+eo/8/,eo_8.html
+eo/9/,eo_9.html
+eo/10/,eo_10.html
+eo/11/,eo_11.html
+eo/12/,eo_12.html
+eo/13/,eo_13.html
+eo/x1/,eo_x1.html
+eo/x2/,eo_x2.html
+eo/answers/,eo_answers.html
+eo/dictionary/,eo_dictionary.html
+eo/sitelen_pona/,eo_sitelen_pona.html
+
+pl/,pl_index.html
+pl/0/,pl_0.html
+pl/1/,pl_1.html
+pl/2/,pl_2.html
+pl/3/,pl_3.html
+pl/4/,pl_4.html
+pl/5/,pl_5.html
+pl/6/,pl_6.html
+pl/7/,pl_7.html
+pl/7a/,pl_7a.html
+pl/8/,pl_8.html
+pl/9/,pl_9.html
+pl/10/,pl_10.html
+pl/11/,pl_11.html
+pl/12/,pl_12.html
+pl/13/,pl_13.html
+pl/x1/,pl_x1.html
+pl/x2/,pl_x2.html
+pl/answers/,pl_answers.html
+pl/dictionary/,pl_dictionary.html
+pl/sitelen_pona/,pl_sitelen_pona.html
+
+pt/,pt_index.html
+pt/0/,pt_0.html
+pt/1/,pt_1.html
+pt/2/,pt_2.html
+pt/3/,pt_3.html
+pt/4/,pt_4.html
+pt/5/,pt_5.html
+pt/6/,pt_6.html
+pt/7/,pt_7.html
+pt/7a/,pt_7a.html
+pt/8/,pt_8.html
+pt/9/,pt_9.html
+pt/10/,pt_10.html
+pt/11/,pt_11.html
+pt/12/,pt_12.html
+pt/13/,pt_13.html
+pt/x1/,pt_x1.html
+pt/x2/,pt_x2.html
+pt/answers/,pt_answers.html
+pt/credits/,pt_credits.html
+pt/dictionary/,pt_dictionary.html
+pt/personal_style/,pt_personal_style.html
+pt/sitelen_pona/,pt_sitelen_pona.html
+
+ru/,ru_index.html
+ru/0/,ru_0.html
+ru/1/,ru_1.html
+ru/2/,ru_2.html
+ru/3/,ru_3.html
+ru/4/,ru_4.html
+ru/5/,ru_5.html
+ru/6/,ru_6.html
+ru/7/,ru_7.html
+ru/7a/,ru_7a.html
+ru/8/,ru_8.html
+ru/9/,ru_9.html
+ru/10/,ru_10.html
+ru/11/,ru_11.html
+ru/12/,ru_12.html
+ru/13/,ru_13.html
+ru/13_tonsi/,ru_13_tonsi.html
+ru/x1/,ru_x1.html
+ru/x1_lgbt/,ru_x1_lgbt.html
+ru/x2/,ru_x2.html
+ru/answers/,ru_answers.html
+ru/dictionary/,ru_dictionary.html
+ru/sitelen_pona/,ru_sitelen_pona.html
+
+zh/,zh_index.html
+zh/0/,zh_0.html
+zh/1/,zh_1.html
+zh/2/,zh_2.html
+zh/3/,zh_3.html
+zh/4/,zh_4.html
+zh/5/,zh_5.html
+zh/6/,zh_6.html
+zh/7/,zh_7.html
+zh/7a/,zh_7a.html
+zh/8/,zh_8.html
+zh/9/,zh_9.html
+zh/10/,zh_10.html
+zh/11/,zh_11.html
+zh/12/,zh_12.html
+zh/13/,zh_13.html
+zh/answers/,zh_answers.html