@hutusi/amytis 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.entire/settings.json +4 -0
- package/AGENTS.md +13 -7
- package/CHANGELOG.md +41 -0
- package/CLAUDE.md +30 -2
- package/README.md +84 -58
- package/README.zh.md +195 -0
- package/TODO.md +6 -4
- package/bun.lock +30 -4
- package/content/books/sample-book/images/digital-garden.svg +25 -0
- package/content/books/sample-book/index.mdx +1 -1
- package/content/books/sample-book/introduction.mdx +2 -0
- package/content/posts/2026-01-21-kitchen-sink/index.mdx +26 -1
- package/content/posts/legacy-markdown.md +0 -2
- package/content/posts/markdown-features.mdx +1 -1
- package/content/posts/multilingual-test.mdx +0 -1
- package/content/posts/syntax-highlighting-showcase.mdx +1 -0
- package/content/posts/understanding-react-hooks.mdx +1 -0
- package/content/series/ai-nexus-weekly/index.mdx +1 -1
- package/content/series/digital-garden/01-philosophy.mdx +2 -0
- package/content/series/digital-garden/index.mdx +1 -1
- package/content/series/markdown-showcase/index.mdx +1 -1
- package/content/series/markdown-showcase/syntax-highlighting.mdx +2 -0
- package/content/series/nextjs-deep-dive/01-getting-started.mdx +2 -1
- package/content/series/nextjs-deep-dive/index.mdx +1 -1
- package/content/subscribe.mdx +27 -0
- package/docs/ARCHITECTURE.md +85 -105
- package/docs/CONTRIBUTING.md +11 -3
- package/docs/DIGITAL_GARDEN.md +11 -9
- package/docs/deployment.md +31 -13
- package/eslint.config.mjs +2 -0
- package/package.json +13 -4
- package/packages/create-amytis/package.json +13 -0
- package/packages/create-amytis/src/index.test.ts +187 -0
- package/packages/create-amytis/src/index.ts +230 -0
- package/packages/create-amytis/tsconfig.json +14 -0
- package/public/images/amytis-screenshot.jpg +0 -0
- package/public/images/antelope-canyon.jpg +0 -0
- package/public/images/avatar.jpg +0 -0
- package/public/images/cappadocia.jpg +0 -0
- package/public/images/flowers.jpg +0 -0
- package/public/images/galaxy.jpg +0 -0
- package/public/images/lake.jpg +0 -0
- package/public/images/mountains.jpg +0 -0
- package/public/images/vibrant-waves.avif +0 -0
- package/public/images/wechat-qr.jpg +0 -0
- package/public/next-image-export-optimizer-hashes.json +72 -2
- package/scripts/deploy.ts +77 -0
- package/site.config.example.ts +268 -0
- package/site.config.ts +82 -10
- package/src/app/[slug]/[postSlug]/page.tsx +161 -0
- package/src/app/[slug]/page/[page]/page.tsx +202 -0
- package/src/app/[slug]/page.tsx +162 -7
- package/src/app/archive/page.tsx +5 -8
- package/src/app/books/[slug]/[chapter]/page.tsx +45 -3
- package/src/app/books/[slug]/page.tsx +16 -2
- package/src/app/books/page.tsx +12 -8
- package/src/app/feed.atom/route.ts +62 -0
- package/src/app/feed.xml/route.ts +45 -20
- package/src/app/flows/[year]/[month]/[day]/page.tsx +9 -1
- package/src/app/flows/[year]/page.tsx +1 -1
- package/src/app/flows/page/[page]/page.tsx +2 -0
- package/src/app/flows/page.tsx +4 -0
- package/src/app/globals.css +9 -3
- package/src/app/layout.tsx +22 -1
- package/src/app/notes/[slug]/page.tsx +2 -3
- package/src/app/page.tsx +86 -8
- package/src/app/posts/[slug]/page.tsx +33 -7
- package/src/app/posts/page/[page]/page.tsx +9 -5
- package/src/app/posts/page.tsx +13 -7
- package/src/app/series/[slug]/page/[page]/page.tsx +8 -25
- package/src/app/series/[slug]/page.tsx +21 -19
- package/src/app/series/page.tsx +14 -28
- package/src/app/sitemap.ts +2 -1
- package/src/app/tags/[tag]/page.tsx +1 -1
- package/src/app/tags/page.tsx +1 -1
- package/src/components/Analytics.tsx +34 -36
- package/src/components/AuthorCard.tsx +56 -14
- package/src/components/BookMobileNav.tsx +8 -34
- package/src/components/BookSidebar.tsx +17 -107
- package/src/components/CodeBlock.test.tsx +19 -0
- package/src/components/CodeBlock.tsx +20 -16
- package/src/components/Comments.tsx +4 -3
- package/src/components/CoverImage.tsx +11 -3
- package/src/components/CuratedSeriesSection.tsx +17 -15
- package/src/components/ExternalLinks.tsx +1 -1
- package/src/components/FeaturedStoriesSection.tsx +124 -58
- package/src/components/FlowCalendarSidebar.tsx +10 -7
- package/src/components/FlowContent.tsx +33 -5
- package/src/components/Footer.tsx +28 -6
- package/src/components/Hero.tsx +44 -92
- package/src/components/InlineBookToc.tsx +56 -0
- package/src/components/KnowledgeGraph.tsx +26 -0
- package/src/components/LanguageProvider.tsx +7 -2
- package/src/components/LanguageSwitch.tsx +1 -1
- package/src/components/LatestWritingSection.tsx +12 -22
- package/src/components/MarkdownRenderer.test.tsx +41 -0
- package/src/components/MarkdownRenderer.tsx +43 -8
- package/src/components/Navbar.tsx +24 -15
- package/src/components/NoteSidebar.tsx +6 -76
- package/src/components/Pagination.tsx +2 -2
- package/src/components/PostCard.tsx +2 -1
- package/src/components/PostList.tsx +81 -62
- package/src/components/PostNavigation.tsx +8 -7
- package/src/components/PostSidebar.tsx +12 -107
- package/src/components/PrevNextNav.tsx +63 -0
- package/src/components/RecentNotesSection.tsx +2 -2
- package/src/components/RelatedPosts.tsx +3 -2
- package/src/components/RssFeedWidget.tsx +55 -0
- package/src/components/SectionLabel.tsx +16 -0
- package/src/components/SelectedBooksSection.tsx +12 -15
- package/src/components/SeriesCatalog.tsx +74 -69
- package/src/components/SeriesList.tsx +11 -36
- package/src/components/SeriesSidebar.tsx +4 -2
- package/src/components/TagContentTabs.tsx +17 -12
- package/src/components/TagPageHeader.tsx +12 -2
- package/src/components/TagSidebar.tsx +3 -2
- package/src/components/TagsIndexClient.tsx +1 -1
- package/src/components/TocPanel.tsx +67 -0
- package/src/hooks/useActiveHeading.ts +32 -0
- package/src/hooks/useSidebarAutoScroll.ts +19 -0
- package/src/i18n/translations.ts +26 -4
- package/src/layouts/BookLayout.tsx +10 -40
- package/src/layouts/PostLayout.tsx +37 -26
- package/src/layouts/SimpleLayout.tsx +5 -5
- package/src/lib/feed-utils.ts +68 -0
- package/src/lib/format-utils.test.ts +27 -0
- package/src/lib/format-utils.ts +3 -0
- package/src/lib/image-utils.ts +12 -0
- package/src/lib/json-ld.ts +236 -0
- package/src/lib/markdown.ts +62 -7
- package/src/lib/rehype-image-metadata.test.ts +124 -0
- package/src/lib/rehype-image-metadata.ts +21 -5
- package/src/lib/scroll-utils.ts +11 -0
- package/src/lib/shuffle.ts +21 -0
- package/src/lib/urls.ts +51 -0
- package/tests/e2e/navigation.test.ts +15 -1
- package/tests/integration/books.test.ts +61 -0
- package/tests/integration/feed-utils.test.ts +145 -0
- package/tests/integration/series.test.ts +9 -0
- package/tests/unit/static-params.test.ts +59 -2
- package/src/app/subscribe/page.tsx +0 -17
- package/src/components/SubscribePage.tsx +0 -298
- /package/public/{screenshot.png → images/screenshot.png} +0 -0
package/bun.lock
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"github-slugger": "^2.0.0",
|
|
12
12
|
"gray-matter": "^4.0.3",
|
|
13
13
|
"image-size": "^2.0.2",
|
|
14
|
+
"katex": "^0.16.33",
|
|
14
15
|
"mermaid": "^11.12.3",
|
|
15
16
|
"next": "16.1.6",
|
|
16
17
|
"next-image-export-optimizer": "^1.20.1",
|
|
@@ -23,8 +24,12 @@
|
|
|
23
24
|
"rehype-katex": "^7.0.1",
|
|
24
25
|
"rehype-raw": "^7.0.0",
|
|
25
26
|
"rehype-slug": "^6.0.0",
|
|
27
|
+
"rehype-stringify": "^10.0.1",
|
|
26
28
|
"remark-gfm": "^4.0.1",
|
|
27
29
|
"remark-math": "^6.0.0",
|
|
30
|
+
"remark-parse": "^11.0.0",
|
|
31
|
+
"remark-rehype": "^11.1.2",
|
|
32
|
+
"unified": "^11.0.5",
|
|
28
33
|
"unist-util-visit": "^5.1.0",
|
|
29
34
|
"zod": "^4.3.6",
|
|
30
35
|
},
|
|
@@ -32,7 +37,9 @@
|
|
|
32
37
|
"@tailwindcss/postcss": "^4.1.18",
|
|
33
38
|
"@types/bun": "^1.3.9",
|
|
34
39
|
"@types/d3": "^7.4.3",
|
|
40
|
+
"@types/hast": "^3.0.4",
|
|
35
41
|
"@types/image-size": "^0.8.0",
|
|
42
|
+
"@types/mdast": "^4.0.4",
|
|
36
43
|
"@types/node": "^24.10.13",
|
|
37
44
|
"@types/react": "^19.2.14",
|
|
38
45
|
"@types/react-dom": "^19.2.3",
|
|
@@ -46,6 +53,13 @@
|
|
|
46
53
|
"typescript": "^5.9.3",
|
|
47
54
|
},
|
|
48
55
|
},
|
|
56
|
+
"packages/create-amytis": {
|
|
57
|
+
"name": "create-amytis",
|
|
58
|
+
"version": "0.1.0",
|
|
59
|
+
"bin": {
|
|
60
|
+
"create-amytis": "./dist/index.js",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
49
63
|
},
|
|
50
64
|
"trustedDependencies": [
|
|
51
65
|
"sharp",
|
|
@@ -558,7 +572,7 @@
|
|
|
558
572
|
|
|
559
573
|
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
|
560
574
|
|
|
561
|
-
"commander": ["commander@
|
|
575
|
+
"commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
|
562
576
|
|
|
563
577
|
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
|
564
578
|
|
|
@@ -568,6 +582,8 @@
|
|
|
568
582
|
|
|
569
583
|
"cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
|
|
570
584
|
|
|
585
|
+
"create-amytis": ["create-amytis@workspace:packages/create-amytis"],
|
|
586
|
+
|
|
571
587
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
572
588
|
|
|
573
589
|
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
|
@@ -842,6 +858,8 @@
|
|
|
842
858
|
|
|
843
859
|
"hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="],
|
|
844
860
|
|
|
861
|
+
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
|
862
|
+
|
|
845
863
|
"hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="],
|
|
846
864
|
|
|
847
865
|
"hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="],
|
|
@@ -970,7 +988,7 @@
|
|
|
970
988
|
|
|
971
989
|
"jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
|
|
972
990
|
|
|
973
|
-
"katex": ["katex@0.16.
|
|
991
|
+
"katex": ["katex@0.16.33", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA=="],
|
|
974
992
|
|
|
975
993
|
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
|
976
994
|
|
|
@@ -1260,6 +1278,8 @@
|
|
|
1260
1278
|
|
|
1261
1279
|
"rehype-slug": ["rehype-slug@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "github-slugger": "^2.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-to-string": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A=="],
|
|
1262
1280
|
|
|
1281
|
+
"rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="],
|
|
1282
|
+
|
|
1263
1283
|
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
|
|
1264
1284
|
|
|
1265
1285
|
"remark-math": ["remark-math@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-math": "^3.0.0", "micromark-extension-math": "^3.0.0", "unified": "^11.0.0" } }, "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA=="],
|
|
@@ -1504,6 +1524,8 @@
|
|
|
1504
1524
|
|
|
1505
1525
|
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
|
|
1506
1526
|
|
|
1527
|
+
"d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
|
1528
|
+
|
|
1507
1529
|
"d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
|
|
1508
1530
|
|
|
1509
1531
|
"d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
|
|
@@ -1520,16 +1542,20 @@
|
|
|
1520
1542
|
|
|
1521
1543
|
"is-bun-module/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
1522
1544
|
|
|
1523
|
-
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
|
1524
|
-
|
|
1525
1545
|
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
|
1526
1546
|
|
|
1547
|
+
"mermaid/katex": ["katex@0.16.28", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg=="],
|
|
1548
|
+
|
|
1549
|
+
"micromark-extension-math/katex": ["katex@0.16.28", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg=="],
|
|
1550
|
+
|
|
1527
1551
|
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
|
1528
1552
|
|
|
1529
1553
|
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
|
1530
1554
|
|
|
1531
1555
|
"parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
|
|
1532
1556
|
|
|
1557
|
+
"rehype-katex/katex": ["katex@0.16.28", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg=="],
|
|
1558
|
+
|
|
1533
1559
|
"sharp/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
1534
1560
|
|
|
1535
1561
|
"@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<svg width="800" height="400" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="800" height="400" rx="12" fill="#f0fdf4"/>
|
|
3
|
+
<rect x="1" y="1" width="798" height="398" rx="12" fill="none" stroke="#86efac" stroke-width="2"/>
|
|
4
|
+
|
|
5
|
+
<!-- Decorative circles -->
|
|
6
|
+
<circle cx="120" cy="200" r="60" fill="#bbf7d0" opacity="0.6"/>
|
|
7
|
+
<circle cx="680" cy="200" r="60" fill="#bbf7d0" opacity="0.6"/>
|
|
8
|
+
<circle cx="400" cy="100" r="40" fill="#86efac" opacity="0.4"/>
|
|
9
|
+
|
|
10
|
+
<!-- Simple tree/plant shapes -->
|
|
11
|
+
<polygon points="120,220 95,270 145,270" fill="#4ade80"/>
|
|
12
|
+
<rect x="113" y="268" width="14" height="20" fill="#166534"/>
|
|
13
|
+
<polygon points="120,190 90,240 150,240" fill="#22c55e"/>
|
|
14
|
+
|
|
15
|
+
<polygon points="680,220 655,270 705,270" fill="#4ade80"/>
|
|
16
|
+
<rect x="673" y="268" width="14" height="20" fill="#166534"/>
|
|
17
|
+
<polygon points="680,190 650,240 710,240" fill="#22c55e"/>
|
|
18
|
+
|
|
19
|
+
<!-- Title text -->
|
|
20
|
+
<text x="400" y="175" text-anchor="middle" font-family="Georgia, serif" font-size="42" font-weight="bold" fill="#14532d">The Digital Garden</text>
|
|
21
|
+
<text x="400" y="225" text-anchor="middle" font-family="Georgia, serif" font-size="22" font-style="italic" fill="#166534">A place for ideas to grow</text>
|
|
22
|
+
|
|
23
|
+
<!-- Subtitle -->
|
|
24
|
+
<text x="400" y="310" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#4ade80">✦ cultivate · connect · contribute ✦</text>
|
|
25
|
+
</svg>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "The Digital Garden Handbook"
|
|
3
3
|
excerpt: "A comprehensive guide to building and maintaining your own digital garden, from initial setup to advanced techniques."
|
|
4
4
|
date: "2026-01-15"
|
|
5
|
-
coverImage: "
|
|
5
|
+
coverImage: "/images/flowers.jpg"
|
|
6
6
|
featured: true
|
|
7
7
|
draft: false
|
|
8
8
|
authors: ["Amytis"]
|
|
@@ -3,6 +3,8 @@ title: "Introduction to Digital Gardens"
|
|
|
3
3
|
excerpt: "Understanding the philosophy and history behind digital gardens."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+

|
|
7
|
+
|
|
6
8
|
## What is a Digital Garden?
|
|
7
9
|
|
|
8
10
|
A digital garden is a personal online space where ideas are cultivated over time. Unlike a traditional blog with polished, finished posts, a digital garden embraces the concept of learning in public.
|
|
@@ -7,7 +7,7 @@ tags: ["features", "test", "demo"]
|
|
|
7
7
|
authors: ["Amytis Team", "Tester"]
|
|
8
8
|
layout: "post"
|
|
9
9
|
latex: true
|
|
10
|
-
toc:
|
|
10
|
+
toc: true
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Heading Level 1
|
|
@@ -128,6 +128,31 @@ sequenceDiagram
|
|
|
128
128
|
### Raw HTML (Quoted)
|
|
129
129
|
<img src="./assets/test.svg" width="100" alt="Small HTML Image" style="border: 2px solid #ccc; border-radius: 8px;" />
|
|
130
130
|
|
|
131
|
+
### Photos from Public Directory
|
|
132
|
+
|
|
133
|
+

|
|
134
|
+
|
|
135
|
+

|
|
136
|
+
|
|
137
|
+

|
|
138
|
+
|
|
139
|
+

|
|
140
|
+
|
|
141
|
+

|
|
142
|
+
|
|
143
|
+

|
|
144
|
+
|
|
145
|
+
### Vibrant Waves (AVIF format)
|
|
146
|
+
|
|
147
|
+

|
|
148
|
+
|
|
149
|
+
### Side by Side (Raw HTML)
|
|
150
|
+
|
|
151
|
+
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
|
152
|
+
<img src="/images/antelope-canyon.jpg" alt="Antelope Canyon" style="width: 48%; border-radius: 8px;" />
|
|
153
|
+
<img src="/images/cappadocia.jpg" alt="Cappadocia" style="width: 48%; border-radius: 8px;" />
|
|
154
|
+
</div>
|
|
155
|
+
|
|
131
156
|
---
|
|
132
157
|
|
|
133
158
|
## Tables
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "AI Nexus Weekly"
|
|
3
3
|
excerpt: "A curated weekly digest exploring the rapidly evolving landscape of Artificial Intelligence, from large language models to robotics."
|
|
4
4
|
date: "2026-02-17"
|
|
5
|
-
coverImage: "
|
|
5
|
+
coverImage: "/images/galaxy.jpg"
|
|
6
6
|
featured: true
|
|
7
7
|
sort: "date-desc"
|
|
8
8
|
---
|
|
@@ -5,6 +5,8 @@ excerpt: "How ideas evolve from raw daily flows into articles, series, and books
|
|
|
5
5
|
category: "Philosophy"
|
|
6
6
|
tags: ["pkm", "knowledge management", "learning"]
|
|
7
7
|
authors: ["Amytis Team"]
|
|
8
|
+
featured: true
|
|
9
|
+
coverImage: "/images/mountains.jpg"
|
|
8
10
|
---
|
|
9
11
|
|
|
10
12
|
# The Philosophy of Digital Gardening
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "The Digital Garden"
|
|
3
3
|
excerpt: "Exploring the philosophy and architecture of modern digital gardens. A journey from linear blogs to non-linear knowledge systems."
|
|
4
4
|
date: "2026-02-11"
|
|
5
|
-
coverImage: "
|
|
5
|
+
coverImage: "/images/mountains.jpg"
|
|
6
6
|
featured: true
|
|
7
7
|
sort: "manual"
|
|
8
8
|
posts: ["01-philosophy", "02-architecture"]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "Markdown Showcase"
|
|
3
3
|
excerpt: "A comprehensive tour of the rich content features supported by Amytis, from Mermaid diagrams to LaTeX math."
|
|
4
4
|
date: "2026-02-13"
|
|
5
|
-
coverImage: "
|
|
5
|
+
coverImage: "/images/lake.jpg"
|
|
6
6
|
featured: true
|
|
7
7
|
sort: "manual"
|
|
8
8
|
posts: ["visuals-and-diagrams", "mathematical-notation", "syntax-highlighting"]
|
|
@@ -3,6 +3,8 @@ title: "Syntax Highlighting"
|
|
|
3
3
|
date: "2026-02-15"
|
|
4
4
|
category: "Engineering"
|
|
5
5
|
tags: ["code", "typescript"]
|
|
6
|
+
featured: true
|
|
7
|
+
coverImage: "/images/vibrant-waves.avif"
|
|
6
8
|
---
|
|
7
9
|
|
|
8
10
|
Amytis provides beautiful syntax highlighting for dozens of programming languages. Here are a few examples within the series context.
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
title: "Part 1: Getting Started with Next.js 15"
|
|
3
3
|
date: "2026-01-30"
|
|
4
4
|
excerpt: "Setting up the environment and understanding the core philosophy."
|
|
5
|
-
|
|
5
|
+
featured: true
|
|
6
|
+
coverImage: "/images/vibrant-waves.avif"
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# Getting Started
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
title: "Next.js Deep Dive"
|
|
3
3
|
excerpt: "A comprehensive guide to mastering Next.js 15, including advanced routing, data fetching, and performance optimization."
|
|
4
4
|
date: "2026-01-30"
|
|
5
|
-
coverImage: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?auto=format&fit=crop&w=800&q=80"
|
|
6
5
|
sort: "manual"
|
|
6
|
+
coverImage: "/images/cappadocia.jpg"
|
|
7
7
|
posts:
|
|
8
8
|
- "01-getting-started"
|
|
9
9
|
- "02-routing-mastery"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Subscribe"
|
|
3
|
+
excerpt: "Stay updated with new posts and notes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Choose how you'd like to follow along.
|
|
7
|
+
|
|
8
|
+
## RSS Feed
|
|
9
|
+
|
|
10
|
+
RSS is an open standard — no account required. Paste the feed URL into any reader app, or use one of the quick-subscribe links below.
|
|
11
|
+
|
|
12
|
+
<rss-feed></rss-feed>
|
|
13
|
+
|
|
14
|
+
**Popular readers:** [Follow](https://app.follow.is) · [Feedly](https://feedly.com) · [Inoreader](https://www.inoreader.com) · [NetNewsWire](https://netnewswire.com) · [NewsBlur](https://newsblur.com)
|
|
15
|
+
|
|
16
|
+
## Newsletter
|
|
17
|
+
|
|
18
|
+
Subscribe via email to get new posts delivered to your inbox.
|
|
19
|
+
|
|
20
|
+
[Subscribe →](https://example.com)
|
|
21
|
+
|
|
22
|
+
## Social
|
|
23
|
+
|
|
24
|
+
Follow for updates and discussions.
|
|
25
|
+
|
|
26
|
+
- [X (Twitter)](https://twitter.com)
|
|
27
|
+
- [GitHub](https://github.com)
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,120 +1,100 @@
|
|
|
1
1
|
# Architecture Overview
|
|
2
2
|
|
|
3
|
-
Amytis is a static
|
|
3
|
+
Amytis is a static-export-first Next.js 16 App Router project for Markdown/MDX publishing across posts, series, books, flows, and notes.
|
|
4
4
|
|
|
5
5
|
## Core Stack
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
7
|
+
- Framework: Next.js 16.1.6 + React 19
|
|
8
|
+
- Runtime/tooling: Bun
|
|
9
|
+
- Styling: Tailwind CSS v4 + CSS variables + `next-themes`
|
|
10
|
+
- Content parsing: `gray-matter` + Zod validation in `src/lib/markdown.ts`
|
|
11
|
+
- Search: Pagefind (`/pagefind/pagefind.js` loaded at runtime)
|
|
12
|
+
- Tests: Bun test suites in `src/` and `tests/`
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Content Model
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- **Series:** `getSeriesPosts(slug)` fetches posts for a series.
|
|
23
|
-
- **Book Chapters:** `getBookChapter(bookSlug, chapterSlug)` fetches individual chapter content.
|
|
24
|
-
- **Flows:** `getFlowBySlug(slug)` fetches individual flow entries.
|
|
25
|
-
- **Static Generation:** `generateStaticParams` is implemented in dynamic routes (`[slug]`, `[page]`, `[tag]`, `[author]`, `[year]`) to pre-render all pages at build time.
|
|
16
|
+
- `content/posts/`: standalone posts (`.md/.mdx`) and folder posts (`index.mdx`)
|
|
17
|
+
- `content/series/<slug>/`: series metadata (`index.mdx`) + series posts
|
|
18
|
+
- `content/books/<slug>/`: book metadata + chapter files
|
|
19
|
+
- `content/flows/YYYY/MM/DD.(md|mdx)`: daily flow entries
|
|
20
|
+
- `content/notes/`: evergreen notes
|
|
21
|
+
- `content/*.mdx`: static pages (about, links, subscribe, privacy, etc.)
|
|
26
22
|
|
|
27
|
-
##
|
|
23
|
+
## Runtime Data Flow
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
1. Source files are read from disk by `src/lib/markdown.ts`.
|
|
26
|
+
2. Frontmatter is parsed and validated (invalid frontmatter throws at build time).
|
|
27
|
+
3. Draft/future filtering and sorting are applied (based on `site.config.ts`).
|
|
28
|
+
4. Route files consume typed helpers (`getAllPosts`, `getBookData`, `getAllFlows`, `getAllNotes`, etc.).
|
|
29
|
+
5. `generateStaticParams()` precomputes dynamic routes for static export.
|
|
30
|
+
|
|
31
|
+
## Route Map (App Router)
|
|
32
|
+
|
|
33
|
+
```text
|
|
30
34
|
src/app/
|
|
31
|
-
page.tsx # Homepage
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
tags/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
[slug]/page.tsx # Static pages (about, etc.)
|
|
35
|
+
page.tsx # Homepage
|
|
36
|
+
page/[page]/page.tsx # Homepage pagination
|
|
37
|
+
layout.tsx # Root layout/providers
|
|
38
|
+
posts/page.tsx # Posts index
|
|
39
|
+
posts/page/[page]/page.tsx # Posts pagination
|
|
40
|
+
posts/[slug]/page.tsx # Canonical post route
|
|
41
|
+
series/page.tsx # Series index
|
|
42
|
+
series/[slug]/page.tsx # Series detail
|
|
43
|
+
series/[slug]/page/[page]/page.tsx
|
|
44
|
+
books/page.tsx # Books index
|
|
45
|
+
books/[slug]/page.tsx # Book landing
|
|
46
|
+
books/[slug]/[chapter]/page.tsx # Book chapter
|
|
47
|
+
flows/page.tsx # Flow index
|
|
48
|
+
flows/page/[page]/page.tsx # Flow pagination
|
|
49
|
+
flows/[year]/page.tsx
|
|
50
|
+
flows/[year]/[month]/page.tsx
|
|
51
|
+
flows/[year]/[month]/[day]/page.tsx
|
|
52
|
+
notes/page.tsx # Notes index
|
|
53
|
+
notes/page/[page]/page.tsx
|
|
54
|
+
notes/[slug]/page.tsx
|
|
55
|
+
tags/page.tsx
|
|
56
|
+
tags/[tag]/page.tsx
|
|
57
|
+
authors/[author]/page.tsx
|
|
58
|
+
archive/page.tsx
|
|
59
|
+
graph/page.tsx
|
|
60
|
+
feed.xml/route.ts
|
|
61
|
+
search.json/route.ts
|
|
62
|
+
sitemap.ts
|
|
63
|
+
[slug]/page.tsx # Static pages + custom series listing path
|
|
64
|
+
[slug]/page/[page]/page.tsx # Custom series listing pagination
|
|
65
|
+
[slug]/[postSlug]/page.tsx # Custom post basePath/series post path
|
|
63
66
|
```
|
|
64
67
|
|
|
65
|
-
##
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
### Navigation & Discovery
|
|
89
|
-
- **`TableOfContents`** - Sticky TOC with scroll-based tracking.
|
|
90
|
-
- **`Search`** - Full-text search modal (Cmd/Ctrl+K) powered by Pagefind. Supports type filter tabs (All/Post/Flow/Book), recent searches, keyboard navigation, debounced input, focus trap, and ARIA accessibility. Search syntax: `"exact phrase"`, `word1 word2` (AND), `-exclude`.
|
|
91
|
-
- **`Pagination`** - Previous/Next page navigation.
|
|
92
|
-
- **`ReadingProgressBar`** - Top-of-page progress bar for book chapters.
|
|
93
|
-
- **`SubscribePage`** - Centralized page for all subscription options.
|
|
94
|
-
|
|
95
|
-
## Data Access Layer (`src/lib/markdown.ts`)
|
|
96
|
-
|
|
97
|
-
| Function | Returns | Purpose |
|
|
98
|
-
|----------|---------|---------|
|
|
99
|
-
| `getAllPosts()` | `PostData[]` | All posts, filtered and sorted |
|
|
100
|
-
| `getAllFlows()` | `FlowData[]` | All daily notes, sorted by date |
|
|
101
|
-
| `getAllBooks()` | `BookData[]` | All books metadata |
|
|
102
|
-
| `getBookData(slug)` | `BookData \| null` | Single book metadata & TOC |
|
|
103
|
-
| `getBookChapter(...)` | `BookChapterData` | Single chapter content |
|
|
104
|
-
| `getAllNotes()` | `NoteData[]` | All notes, sorted by date |
|
|
105
|
-
| `getNoteBySlug(slug)` | `NoteData \| null` | Single note content |
|
|
106
|
-
| `getBacklinks(slug)` | `BacklinkSource[]` | Inbound links for a page |
|
|
107
|
-
| `getFlowBySlug(slug)` | `FlowData \| null` | Single flow entry |
|
|
108
|
-
| `getSeriesPosts(slug)` | `PostData[]` | Posts in a series |
|
|
109
|
-
| `calculateReadingTime(content)` | `string` | Estimated reading time (multilingual) |
|
|
110
|
-
|
|
111
|
-
## Theming
|
|
112
|
-
|
|
113
|
-
Theming is handled by `next-themes` and Tailwind CSS v4. `src/app/globals.css` defines CSS variables for palettes (`default`, `blue`, `rose`, `amber`).
|
|
68
|
+
## URL Routing Rules
|
|
69
|
+
|
|
70
|
+
- `next.config.ts` sets `output: "export"` and `trailingSlash: true`.
|
|
71
|
+
- Post URLs use `getPostUrl()` in `src/lib/urls.ts`:
|
|
72
|
+
- Default: `/<posts.basePath>/<post.slug>` (basePath defaults to `posts`)
|
|
73
|
+
- Series override: `/<series.customPaths[seriesSlug]>/<post.slug>`
|
|
74
|
+
- Dynamic route params should return raw segment values from `generateStaticParams()` (do not pre-encode values).
|
|
75
|
+
|
|
76
|
+
## Key Components
|
|
77
|
+
|
|
78
|
+
- Layout/navigation: `Navbar`, `Footer`, `Hero`, `FlowHubTabs`
|
|
79
|
+
- Content renderers: `MarkdownRenderer`, `CodeBlock`, `Mermaid`
|
|
80
|
+
- Post surfaces: `PostLayout`, `PostSidebar`, `PostCard`, `RelatedPosts`, `ShareBar`
|
|
81
|
+
- Notes/flows discovery: `NoteSidebar`, `FlowContent`, `FlowCalendarSidebar`, `TagContentTabs`
|
|
82
|
+
- Search/discovery: `Search`, `Pagination`, `KnowledgeGraph`
|
|
83
|
+
|
|
84
|
+
## Data Layer Highlights (`src/lib/markdown.ts`)
|
|
85
|
+
|
|
86
|
+
- Posts/series: `getAllPosts`, `getListingPosts`, `getPostBySlug`, `getSeriesPosts`, `getSeriesData`
|
|
87
|
+
- Books: `getAllBooks`, `getBookData`, `getBookChapter`
|
|
88
|
+
- Flows: `getAllFlows`, `getFlowBySlug`, `getFlowsByYear`, `getFlowsByMonth`
|
|
89
|
+
- Notes: `getAllNotes`, `getNoteBySlug`, `getNotesByTag`
|
|
90
|
+
- Discovery: `buildSlugRegistry`, `getBacklinks`, `getAllTags`, `getAllAuthors`
|
|
114
91
|
|
|
115
92
|
## Build Pipeline
|
|
116
93
|
|
|
117
|
-
1.
|
|
118
|
-
2.
|
|
119
|
-
3.
|
|
120
|
-
4.
|
|
94
|
+
1. `bun scripts/copy-assets.ts`: copy co-located media into `public/`
|
|
95
|
+
2. `bun run build:graph`: generate graph data
|
|
96
|
+
3. `next build`: static export to `out/`
|
|
97
|
+
4. Production only (`bun run build`): `next-image-export-optimizer`
|
|
98
|
+
5. Pagefind indexing:
|
|
99
|
+
- Production: `pagefind --site out` (writes to `out/pagefind`)
|
|
100
|
+
- Dev build: `pagefind --site out --output-path public/pagefind`
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -62,9 +62,6 @@ Notes live in `content/notes/`.
|
|
|
62
62
|
```bash
|
|
63
63
|
# Create a new note using the dedicated script
|
|
64
64
|
bun run new-note "Zettelkasten Method"
|
|
65
|
-
|
|
66
|
-
# Or using the general new script
|
|
67
|
-
bun run new "Zettelkasten Method" --note
|
|
68
65
|
```
|
|
69
66
|
|
|
70
67
|
### Importing Content
|
|
@@ -96,7 +93,9 @@ bun run series-draft "my-series" --undraft
|
|
|
96
93
|
```bash
|
|
97
94
|
bun test # Run all tests
|
|
98
95
|
bun run test:unit # Run unit tests
|
|
96
|
+
bun run test:int # Run integration tests
|
|
99
97
|
bun run test:e2e # Run end-to-end tests
|
|
98
|
+
bun run validate # Lint + test + build:dev
|
|
100
99
|
```
|
|
101
100
|
|
|
102
101
|
## Building
|
|
@@ -106,6 +105,15 @@ bun run build # Production build (includes image optimization and P
|
|
|
106
105
|
bun run build:dev # Development build (faster, no image optimization; also generates Pagefind index)
|
|
107
106
|
```
|
|
108
107
|
|
|
108
|
+
## Static Export Routing Rules
|
|
109
|
+
|
|
110
|
+
Amytis relies on static export (`output: "export"`) with `trailingSlash: true`.
|
|
111
|
+
|
|
112
|
+
- In `generateStaticParams()`, return raw segment values and let Next.js handle encoding.
|
|
113
|
+
- Do not pre-encode route params with `encodeURIComponent`.
|
|
114
|
+
- Do not link to placeholder routes such as `/posts/[slug]`; always link to concrete URLs.
|
|
115
|
+
- When touching dynamic routes, verify both ASCII and Unicode slugs.
|
|
116
|
+
|
|
109
117
|
## Code Style
|
|
110
118
|
|
|
111
119
|
- **Linting:** `bun run lint`
|