setup server
Seto committed
Dec 2, 2025 at 21:41 UTC
fa2c66f14d17510d5336a8d8d4a26cce87127fdf
5 files changed
+168
-5
astro.config.ts
+17
-5
@@ -12,23 +12,29 @@ import rehypeCopyCode from './src/plugins/rehype-copy-code.mjs'
12
import remarkTOC from './src/plugins/remark-toc.mjs'
13
import { SITE } from './src/config'
14
import path from 'path'
15
-
16
-import tailwindcss from '@tailwindcss/vite';
15
+import tailwindcss from '@tailwindcss/vite'
16
+import node from '@astrojs/node'
17
18
export default defineConfig({
19
site: SITE.website,
20
+ base: '/',
21
+
22
devToolbar: {
23
enabled: false
24
},
23
- output: 'static',
25
+
26
+ output: 'server',
27
+
28
build: {
29
inlineStylesheets: 'auto'
30
},
31
+
32
image: {
33
service: {
34
entrypoint: 'astro/assets/services/sharp'
35
}
36
},
37
+
38
markdown: {
39
shikiConfig: {
40
theme: 'css-variables',
@@ -37,7 +43,9 @@ export default defineConfig({
43
remarkPlugins: [remarkMath, remarkDirective, remarkEmbeddedMedia, remarkReadingTime, remarkTOC],
44
rehypePlugins: [rehypeKatex, rehypeCleanup, rehypeImageProcessor, rehypeCopyCode]
45
},
46
+
47
integrations: [mdx(), sitemap()],
48
+
49
vite: {
50
resolve: {
51
alias: {
@@ -61,5 +69,9 @@ export default defineConfig({
69
},
70
71
plugins: [tailwindcss()]
64
- }
65
-})
\ No newline at end of file
72
+ },
73
+
74
+ adapter: node({
75
+ mode: 'middleware'
76
+ })
77
+})
package.json
+1
@@ -19,6 +19,7 @@
19
},
20
"dependencies": {
21
"@astrojs/mdx": "^4.3.12",
22
+ "@astrojs/node": "^9.5.1",
23
"@astrojs/sitemap": "^3.6.0",
24
"@tailwindcss/vite": "^4.1.17",
25
"astro": "^5.16.3",
pnpm-lock.yaml
+138
@@ -11,6 +11,9 @@ importers:
11
'@astrojs/mdx':
12
specifier: ^4.3.12
13
version: 4.3.12(astro@5.16.3(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3))
14
+ '@astrojs/node':
15
+ specifier: ^9.5.1
16
+ version: 9.5.1(astro@5.16.3(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3))
17
'@astrojs/sitemap':
18
specifier: ^3.6.0
19
version: 3.6.0
@@ -102,6 +105,11 @@ packages:
105
peerDependencies:
106
astro: ^5.0.0
107
108
+ '@astrojs/node@9.5.1':
109
+ resolution: {integrity: sha512-7k+SU877OUQylPr0mFcWrGvNuC78Lp9w+GInY8Rwc+LkHyDP9xls+nZAioK0WDWd+fyeQnlHbpDGURO3ZHuDVg==}
110
+ peerDependencies:
111
+ astro: ^5.14.3
112
+
113
'@astrojs/prism@3.3.0':
114
resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
115
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
@@ -1259,6 +1267,10 @@ packages:
1267
defu@6.1.4:
1268
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
1269
1270
+ depd@2.0.0:
1271
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
1272
+ engines: {node: '>= 0.8'}
1273
+
1274
dequal@2.0.3:
1275
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
1276
engines: {node: '>=6'}
@@ -1307,12 +1319,19 @@ packages:
1319
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
1320
engines: {node: '>=4'}
1321
1322
+ ee-first@1.1.1:
1323
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
1324
+
1325
emoji-regex@10.6.0:
1326
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
1327
1328
emoji-regex@8.0.0:
1329
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
1330
1331
+ encodeurl@2.0.0:
1332
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
1333
+ engines: {node: '>= 0.8'}
1334
+
1335
enhanced-resolve@5.18.3:
1336
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
1337
engines: {node: '>=10.13.0'}
@@ -1344,6 +1363,9 @@ packages:
1363
engines: {node: '>=18'}
1364
hasBin: true
1365
1366
+ escape-html@1.0.3:
1367
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
1368
+
1369
escape-string-regexp@4.0.0:
1370
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
1371
engines: {node: '>=10'}
@@ -1436,6 +1458,10 @@ packages:
1458
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
1459
engines: {node: '>=0.10.0'}
1460
1461
+ etag@1.8.1:
1462
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
1463
+ engines: {node: '>= 0.6'}
1464
+
1465
eventemitter3@5.0.1:
1466
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
1467
@@ -1496,6 +1522,10 @@ packages:
1522
fontkit@2.0.4:
1523
resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==}
1524
1525
+ fresh@2.0.0:
1526
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
1527
+ engines: {node: '>= 0.8'}
1528
+
1529
fsevents@2.3.3:
1530
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
1531
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1591,6 +1621,10 @@ packages:
1621
http-cache-semantics@4.2.0:
1622
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
1623
1624
+ http-errors@2.0.1:
1625
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
1626
+ engines: {node: '>= 0.8'}
1627
+
1628
ignore@5.3.2:
1629
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
1630
engines: {node: '>= 4'}
@@ -1610,6 +1644,9 @@ packages:
1644
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
1645
engines: {node: '>=0.8.19'}
1646
1647
+ inherits@2.0.4:
1648
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
1649
+
1650
inline-style-parser@0.2.7:
1651
resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
1652
@@ -1975,6 +2012,14 @@ packages:
2012
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
2013
engines: {node: '>=8.6'}
2014
2015
+ mime-db@1.54.0:
2016
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
2017
+ engines: {node: '>= 0.6'}
2018
+
2019
+ mime-types@3.0.2:
2020
+ resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
2021
+ engines: {node: '>=18'}
2022
+
2023
minimatch@3.1.2:
2024
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
2025
@@ -2023,6 +2068,10 @@ packages:
2068
ohash@2.0.11:
2069
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
2070
2071
+ on-finished@2.4.1:
2072
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
2073
+ engines: {node: '>= 0.8'}
2074
+
2075
oniguruma-parser@0.12.1:
2076
resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
2077
@@ -2139,6 +2188,10 @@ packages:
2188
radix3@1.1.2:
2189
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
2190
2191
+ range-parser@1.2.1:
2192
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
2193
+ engines: {node: '>= 0.6'}
2194
+
2195
readdirp@4.1.2:
2196
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
2197
engines: {node: '>= 14.18.0'}
@@ -2260,6 +2313,16 @@ packages:
2313
engines: {node: '>=10'}
2314
hasBin: true
2315
2316
+ send@1.2.0:
2317
+ resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
2318
+ engines: {node: '>= 18'}
2319
+
2320
+ server-destroy@1.0.1:
2321
+ resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
2322
+
2323
+ setprototypeof@1.2.0:
2324
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
2325
+
2326
sharp@0.34.5:
2327
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
2328
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -2298,6 +2361,10 @@ packages:
2361
space-separated-tokens@2.0.2:
2362
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
2363
2364
+ statuses@2.0.2:
2365
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
2366
+ engines: {node: '>= 0.8'}
2367
+
2368
stream-replace-string@2.0.0:
2369
resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}
2370
@@ -2368,6 +2435,10 @@ packages:
2435
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
2436
engines: {node: '>=8.0'}
2437
2438
+ toidentifier@1.0.1:
2439
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
2440
+ engines: {node: '>=0.6'}
2441
+
2442
trim-lines@3.0.1:
2443
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
2444
@@ -2712,6 +2783,15 @@ snapshots:
2783
transitivePeerDependencies:
2784
- supports-color
2785
2786
+ '@astrojs/node@9.5.1(astro@5.16.3(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3))':
2787
+ dependencies:
2788
+ '@astrojs/internal-helpers': 0.7.5
2789
+ astro: 5.16.3(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)
2790
+ send: 1.2.0
2791
+ server-destroy: 1.0.1
2792
+ transitivePeerDependencies:
2793
+ - supports-color
2794
+
2795
'@astrojs/prism@3.3.0':
2796
dependencies:
2797
prismjs: 1.30.0
@@ -3760,6 +3840,8 @@ snapshots:
3840
3841
defu@6.1.4: {}
3842
3843
+ depd@2.0.0: {}
3844
+
3845
dequal@2.0.3: {}
3846
3847
destr@2.0.5: {}
@@ -3802,10 +3884,14 @@ snapshots:
3884
3885
dset@3.1.4: {}
3886
3887
+ ee-first@1.1.1: {}
3888
+
3889
emoji-regex@10.6.0: {}
3890
3891
emoji-regex@8.0.0: {}
3892
3893
+ encodeurl@2.0.0: {}
3894
+
3895
enhanced-resolve@5.18.3:
3896
dependencies:
3897
graceful-fs: 4.2.11
@@ -3889,6 +3975,8 @@ snapshots:
3975
'@esbuild/win32-ia32': 0.27.0
3976
'@esbuild/win32-x64': 0.27.0
3977
3978
+ escape-html@1.0.3: {}
3979
+
3980
escape-string-regexp@4.0.0: {}
3981
3982
escape-string-regexp@5.0.0: {}
@@ -4019,6 +4107,8 @@ snapshots:
4107
4108
esutils@2.0.3: {}
4109
4110
+ etag@1.8.1: {}
4111
+
4112
eventemitter3@5.0.1: {}
4113
4114
extend@3.0.2: {}
@@ -4084,6 +4174,8 @@ snapshots:
4174
unicode-properties: 1.4.1
4175
unicode-trie: 2.0.0
4176
4177
+ fresh@2.0.0: {}
4178
+
4179
fsevents@2.3.3:
4180
optional: true
4181
@@ -4272,6 +4364,14 @@ snapshots:
4364
4365
http-cache-semantics@4.2.0: {}
4366
4367
+ http-errors@2.0.1:
4368
+ dependencies:
4369
+ depd: 2.0.0
4370
+ inherits: 2.0.4
4371
+ setprototypeof: 1.2.0
4372
+ statuses: 2.0.2
4373
+ toidentifier: 1.0.1
4374
+
4375
ignore@5.3.2: {}
4376
4377
ignore@7.0.5: {}
@@ -4285,6 +4385,8 @@ snapshots:
4385
4386
imurmurhash@0.1.4: {}
4387
4388
+ inherits@2.0.4: {}
4389
+
4390
inline-style-parser@0.2.7: {}
4391
4392
iron-webcrypto@1.2.1: {}
@@ -4914,6 +5016,12 @@ snapshots:
5016
braces: 3.0.3
5017
picomatch: 2.3.1
5018
5019
+ mime-db@1.54.0: {}
5020
+
5021
+ mime-types@3.0.2:
5022
+ dependencies:
5023
+ mime-db: 1.54.0
5024
+
5025
minimatch@3.1.2:
5026
dependencies:
5027
brace-expansion: 1.1.12
@@ -4954,6 +5062,10 @@ snapshots:
5062
5063
ohash@2.0.11: {}
5064
5065
+ on-finished@2.4.1:
5066
+ dependencies:
5067
+ ee-first: 1.1.1
5068
+
5069
oniguruma-parser@0.12.1: {}
5070
5071
oniguruma-to-es@4.3.4:
@@ -5071,6 +5183,8 @@ snapshots:
5183
5184
radix3@1.1.2: {}
5185
5186
+ range-parser@1.2.1: {}
5187
+
5188
readdirp@4.1.2: {}
5189
5190
reading-time@1.5.0: {}
@@ -5298,6 +5412,26 @@ snapshots:
5412
5413
semver@7.7.3: {}
5414
5415
+ send@1.2.0:
5416
+ dependencies:
5417
+ debug: 4.4.3
5418
+ encodeurl: 2.0.0
5419
+ escape-html: 1.0.3
5420
+ etag: 1.8.1
5421
+ fresh: 2.0.0
5422
+ http-errors: 2.0.1
5423
+ mime-types: 3.0.2
5424
+ ms: 2.1.3
5425
+ on-finished: 2.4.1
5426
+ range-parser: 1.2.1
5427
+ statuses: 2.0.2
5428
+ transitivePeerDependencies:
5429
+ - supports-color
5430
+
5431
+ server-destroy@1.0.1: {}
5432
+
5433
+ setprototypeof@1.2.0: {}
5434
+
5435
sharp@0.34.5:
5436
dependencies:
5437
'@img/colour': 1.0.0
@@ -5363,6 +5497,8 @@ snapshots:
5497
5498
space-separated-tokens@2.0.2: {}
5499
5500
+ statuses@2.0.2: {}
5501
+
5502
stream-replace-string@2.0.0: {}
5503
5504
string-width@4.2.3:
@@ -5439,6 +5575,8 @@ snapshots:
5575
dependencies:
5576
is-number: 7.0.0
5577
5578
+ toidentifier@1.0.1: {}
5579
+
5580
trim-lines@3.0.1: {}
5581
5582
trough@2.2.0: {}
run-server.js
new
+11
@@ -0,0 +1,11 @@
1
+import express from 'express'
2
+import { handler as ssrHandler } from './dist/server/entry.mjs'
3
+
4
+const app = express()
5
+// Change this based on your astro.config.mjs, `base` option.
6
+// They should match. The default value is "/".
7
+const base = '/'
8
+app.use(base, express.static('dist/client/'))
9
+app.use(ssrHandler)
10
+
11
+app.listen(3021)
src/pages/[...slug].astro
+1
@@ -1,4 +1,5 @@
1
---
2
+export const prerender = true
3
import { type CollectionEntry, getCollection } from 'astro:content'
4
import PostLayout from '@/layouts/PostLayout.astro'
5
import { render } from 'astro:content'