Compare commits
1201 Commits
dev/shadcn
...
cloudflare
Author | SHA1 | Date | |
---|---|---|---|
|
2a6e322c0a | ||
|
37f011cf74 | ||
|
35d0ca9e12 | ||
|
34baf20b31 | ||
|
28fcbae6a2 | ||
|
fc8cea13cd | ||
|
6065c4af06 | ||
|
ba7b950c01 | ||
|
c94784e711 | ||
|
48c045fb73 | ||
|
3fd47869a2 | ||
|
e3ac4a0a29 | ||
|
47adbcfd06 | ||
|
5d5eb82013 | ||
|
b0a065ced9 | ||
|
794c18a7e6 | ||
|
9899e1d164 | ||
|
ad1cbedb56 | ||
|
3707500ed8 | ||
|
f36018945d | ||
|
9f5d4aec59 | ||
|
e3f44a85a5 | ||
|
1f9a7c2621 | ||
|
a92ef86a71 | ||
|
e2dfab2ca7 | ||
|
e5061b3b67 | ||
|
4faa89c0ee | ||
|
481f3268db | ||
|
66d7dd3259 | ||
|
9aeb59dff2 | ||
|
2faedc2043 | ||
|
c0aa979382 | ||
|
fa2e981c16 | ||
|
0c415ee24b | ||
|
21eee041ab | ||
|
6c584c75e2 | ||
|
797ee9b7e5 | ||
|
658409cfbd | ||
|
422c323467 | ||
|
de7e87e5b8 | ||
|
613bbd0d78 | ||
|
4434f1900d | ||
|
895e02bfdd | ||
|
7cc1fd5835 | ||
|
4bad9714fa | ||
|
fa4b9a19a1 | ||
|
1c0c46fa34 | ||
|
0ae3f27c78 | ||
|
fc024ea0da | ||
|
80851fcf44 | ||
|
31829ce17b | ||
|
7c9b0a2697 | ||
|
5f14259197 | ||
|
15da1ee48a | ||
|
c2d7e51f5b | ||
|
00405d5335 | ||
|
610346055f | ||
|
cb9c3132fd | ||
|
32fc3d6dc9 | ||
|
69143ace47 | ||
|
8c3ef9bfaf | ||
|
7851a715a3 | ||
|
0fb4ef93d2 | ||
|
95a6f3b9d5 | ||
|
0794c7d297 | ||
|
395f753025 | ||
|
fc53045d99 | ||
|
64ba2711aa | ||
|
3a61c953a4 | ||
|
6de7dfebf3 | ||
|
e626bb9af4 | ||
|
33fe00b8dc | ||
|
2d0392db61 | ||
|
afdaeba2be | ||
|
258ddad399 | ||
|
e6bc1ea9e8 | ||
|
96d630f3ac | ||
|
e15d76461f | ||
|
1ff42009d8 | ||
|
669ac94bad | ||
|
d319bd8af2 | ||
|
01f5734dd5 | ||
|
6837c5a8d4 | ||
|
6927f4b234 | ||
|
ffe5bc4ea5 | ||
|
1be26638fc | ||
|
c66fedea27 | ||
|
b4dab95c04 | ||
|
1e1cafff32 | ||
|
23ddb90e1f | ||
|
8221f1753f | ||
|
18691030e7 | ||
|
7f4a7a61a2 | ||
|
a6a5d92dc1 | ||
|
63a5e4f328 | ||
|
19120ee7f1 | ||
|
7aa7cb5603 | ||
|
d644611afd | ||
|
ca30f95027 | ||
|
8cc16a898c | ||
|
cf8a7f1242 | ||
|
1fb89a2a05 | ||
|
13c23dab56 | ||
|
ac8d4dee4b | ||
|
ff1e72df13 | ||
|
d153ca655e | ||
|
c00223c79a | ||
|
d59be1044a | ||
|
5431160d62 | ||
|
73baf946bd | ||
|
d747683f82 | ||
|
978f13a368 | ||
|
779493965c | ||
|
3ae0411a44 | ||
|
ccf064b0d5 | ||
|
b55613b471 | ||
|
7c0e6a5131 | ||
|
d86f89e3de | ||
|
9800b1d842 | ||
|
9db52f352b | ||
|
47679ab91e | ||
|
90757475ac | ||
|
904dceec44 | ||
|
f468638f49 | ||
|
f1d02720d0 | ||
|
35ddf5e08e | ||
|
bade6b620e | ||
|
d1928575b3 | ||
|
262228d6e9 | ||
|
57b92cfe85 | ||
|
9f2fd58eb0 | ||
|
1f7c38f9f5 | ||
|
9f71c9942a | ||
|
e99d6da45c | ||
|
63dd4e52fb | ||
|
debbb5abf5 | ||
|
c5dfaafe61 | ||
|
df3f3aa895 | ||
|
a1ae6ca384 | ||
|
866988d73c | ||
|
46fd529390 | ||
|
fbb9a1b053 | ||
|
200a9963f7 | ||
|
f6a2df402e | ||
|
0da8f7d335 | ||
|
335c3b46d6 | ||
|
004edeecea | ||
|
f2b5bae866 | ||
|
6bb12a2d86 | ||
|
a1b54d7518 | ||
|
97654d97ea | ||
|
064576f48e | ||
|
0be53d3251 | ||
|
564efbd3e2 | ||
|
2814f87578 | ||
|
78f76f35b9 | ||
|
f50f60443a | ||
|
346d154604 | ||
|
7985769871 | ||
|
aa2e025270 | ||
|
11bfcb731d | ||
|
62eb4124be | ||
|
2b72570784 | ||
|
3c3dcd5d2a | ||
|
89fd7193ac | ||
|
8b2f1848a8 | ||
|
d0ddc2b1b0 | ||
|
6d4d316564 | ||
|
7a61aa3dff | ||
|
46ec614fd3 | ||
|
abb15de848 | ||
|
ba2a2b5fb0 | ||
|
2b8e0b9cb5 | ||
|
d7cc9b956d | ||
|
0b695cc4b2 | ||
|
3cb0911cf4 | ||
|
0d04f6914e | ||
|
22d68c005a | ||
|
70446d10b3 | ||
|
bc4578a3cd | ||
|
971b0d65a0 | ||
|
313c783dbd | ||
|
4384a1d43f | ||
|
7b9b7a0dd7 | ||
|
07ad39871f | ||
|
3d4245e8bc | ||
|
cc56f9d729 | ||
|
5912849fa7 | ||
|
3075681dc8 | ||
|
757f1dc4ae | ||
|
1be38e3e8d | ||
|
716eac324f | ||
|
bd029eac2a | ||
|
2c4db1e744 | ||
|
cb7743fe07 | ||
|
3a81a96316 | ||
|
d7077cb3d4 | ||
|
e5569dabd1 | ||
|
0d5185a789 | ||
|
813d8ea0bb | ||
|
a8c76d3249 | ||
|
49b39ad9dd | ||
|
1adf3d5dc3 | ||
|
5e877bf45e | ||
|
4277970074 | ||
|
b27d8cc505 | ||
|
2d2a85cd26 | ||
|
c960738133 | ||
|
bf8993ca96 | ||
|
a89910489a | ||
|
368644b434 | ||
|
f5e639bbc7 | ||
|
52aeb2d61c | ||
|
7af313868c | ||
|
4313e32471 | ||
|
31116cbf8b | ||
|
8a08dfdf3b | ||
|
141b562307 | ||
|
9fcfb3bdf7 | ||
|
8be9f6c775 | ||
|
ac02ea780a | ||
|
e3aa8eab55 | ||
|
72e0a14fc9 | ||
|
0f79ed14f0 | ||
|
ee341522f5 | ||
|
b4e8585929 | ||
|
b5997ded4c | ||
|
367965e41f | ||
|
c7a1ec69bb | ||
|
4160305a67 | ||
|
a5c6c8b493 | ||
|
4abca022aa | ||
|
765f5e1e39 | ||
|
9f3c5e80c2 | ||
|
997c362ac9 | ||
|
bda2571a78 | ||
|
788fbe2f18 | ||
|
f45bcad110 | ||
|
75db5e85a7 | ||
|
9711d13804 | ||
|
9d4fcbe36d | ||
|
e6663b013d | ||
|
5cb8b0048d | ||
|
0b6f81aca6 | ||
|
6cf9d4db9c | ||
|
59c7c807db | ||
|
de1ccca27b | ||
|
263440742a | ||
|
b75e9eb282 | ||
|
2aeb027e2f | ||
|
0500617803 | ||
|
3872a9d422 | ||
|
2e0a195a2a | ||
|
95bd256bc7 | ||
|
6c1a4685cd | ||
|
bbae584c88 | ||
|
f649db26ae | ||
|
1c7848f6b0 | ||
|
5c213d014a | ||
|
861502c28f | ||
|
737bd7f80f | ||
|
74d7cf44a1 | ||
|
e011d09803 | ||
|
50c500deb5 | ||
|
cd710bb9ed | ||
|
04f7f891a4 | ||
|
c67b804f4f | ||
|
a44e4a669c | ||
|
5af1182a58 | ||
|
24c0334911 | ||
|
3e0861f883 | ||
|
da4b018e8d | ||
|
a7738f0cbf | ||
|
adb9b80572 | ||
|
2e8f70dc76 | ||
|
b94fd34be5 | ||
|
0d4e8fe899 | ||
|
73ce18f564 | ||
|
e430a0c319 | ||
|
f7f7be2ef0 | ||
|
eafb3775e8 | ||
|
0af0aa3b09 | ||
|
04c2b2d7ee | ||
|
d9cda3e122 | ||
|
d8a12343c8 | ||
|
40af0f6922 | ||
|
1740c826c7 | ||
|
75083b32e4 | ||
|
e933844479 | ||
|
13bee49f90 | ||
|
fe2b1bbe39 | ||
|
8a9c76c628 | ||
|
98421afab8 | ||
|
6980507c43 | ||
|
8657bf4e84 | ||
|
bab58e6420 | ||
|
8d17bd80c5 | ||
|
c7e3de816c | ||
|
da26c2cf5d | ||
|
b838ddc293 | ||
|
cc9a15db8f | ||
|
8e63af3e7f | ||
|
aaadd7fcf4 | ||
|
1e2e4d77f7 | ||
|
88bb977c7b | ||
|
abf8b31ec7 | ||
|
12fb19e97b | ||
|
d8904750d9 | ||
|
b30355dfe5 | ||
|
dae7a3b0e8 | ||
|
e0c0ff9518 | ||
|
e1b0e2f44c | ||
|
6195df2bc5 | ||
|
3fa44f92c7 | ||
|
55ae5ced9e | ||
|
111568d746 | ||
|
45e6a59fe6 | ||
|
684bbdff82 | ||
|
181e478bc3 | ||
|
82d0fa1061 | ||
|
ba3cbe0724 | ||
|
91614ed6e5 | ||
|
0453db5ec6 | ||
|
1a297e33f9 | ||
|
05b90fb0a7 | ||
|
66567cfecd | ||
|
46d008e5fc | ||
|
c7cbf96a70 | ||
|
958852335d | ||
|
3058484803 | ||
|
985579b964 | ||
|
b3180e617d | ||
|
bc915a53dc | ||
|
bd67ac3517 | ||
|
e94625ce4e | ||
|
e70a8c92a2 | ||
|
2153cf6771 | ||
|
0164c833db | ||
|
cfbfa409b0 | ||
|
ffbe7f4fb0 | ||
|
13a79c7a01 | ||
|
1cb0793a83 | ||
|
5e1f9167e0 | ||
|
39a2870131 | ||
|
40b313a2f2 | ||
|
9e54932b27 | ||
|
5d50135ed6 | ||
|
befd10cc5b | ||
|
b17599976f | ||
|
107f761716 | ||
|
cb5c588b1e | ||
|
cbfe5e433d | ||
|
7c101d595e | ||
|
196f72ff68 | ||
|
7ab7d2d504 | ||
|
522d8de4ee | ||
|
0739c717d8 | ||
|
71b9807433 | ||
|
e49d4624fe | ||
|
8a72fb2409 | ||
|
e00c22d0fe | ||
|
8a5a49f041 | ||
|
bd8ccf4cf3 | ||
|
fd4426ddd7 | ||
|
fcb58d2206 | ||
|
aa547f209e | ||
|
5b30fd8c48 | ||
|
c8b29c59dc | ||
|
d946e2aead | ||
|
ddd3ee07df | ||
|
da0176ffc5 | ||
|
568ef9bc3a | ||
|
e05d20ee5e | ||
|
56fa6fb63c | ||
|
ebeacae587 | ||
|
7d5f4a52a8 | ||
|
0a2d081b07 | ||
|
21bc0b1293 | ||
|
c477aae333 | ||
|
543798e2c1 | ||
|
483a970b71 | ||
|
292faddc7a | ||
|
8fd3b679fb | ||
|
2d12d89e3b | ||
|
d0aef4b7d4 | ||
|
c006ee750d | ||
|
19a6c4d994 | ||
|
86f13a1748 | ||
|
745ba457df | ||
|
beb53639a3 | ||
|
65fb8722bc | ||
|
160a7eb929 | ||
|
c3d82d9183 | ||
|
767351c5cd | ||
|
fd3c82baaf | ||
|
168eae946f | ||
|
69390fed70 | ||
|
2cb041beb1 | ||
|
3645cf5773 | ||
|
c6ad6d0ad5 | ||
|
53ab869f07 | ||
|
e0f408fb07 | ||
|
1216732a55 | ||
|
4c6fddf99d | ||
|
90d5db88ab | ||
|
af5a3265a6 | ||
|
ec8ce54824 | ||
|
f4d8a09ab6 | ||
|
3b741b3b98 | ||
|
b07be5fab4 | ||
|
a22a5def4d | ||
|
d190bcb358 | ||
|
7f1fe23407 | ||
|
05a7de4599 | ||
|
c098300481 | ||
|
e7240db823 | ||
|
a4390d433b | ||
|
ae49d06cf4 | ||
|
6a448825a6 | ||
|
92a87ceb03 | ||
|
3136766a6d | ||
|
02b5ee1727 | ||
|
b10e27ee29 | ||
|
ea0c74aa12 | ||
|
4015cb3143 | ||
|
2ad6eab666 | ||
|
c23383fdde | ||
|
e610fe7335 | ||
|
a7a5a8a6a4 | ||
|
9ffe9af0fa | ||
|
17c7d67743 | ||
|
0684b16278 | ||
|
9c120d776d | ||
|
a7c56f4a6c | ||
|
563fc2099a | ||
|
56df0bed46 | ||
|
4d60d48212 | ||
|
26a88eb2f0 | ||
|
5b50e62774 | ||
|
c5d08a9846 | ||
|
f5b4ed2859 | ||
|
b88aa9c1f5 | ||
|
593333c3dd | ||
|
f3b6603db7 | ||
|
9cb559a48d | ||
|
c3392320b3 | ||
|
708fac652f | ||
|
ec124640f1 | ||
|
862132d8eb | ||
|
bf11c143fe | ||
|
6cfc76d621 | ||
|
d935bcff76 | ||
|
a727a31e2f | ||
|
2cdc520b1d | ||
|
81cfc5f6b3 | ||
|
8e8291c325 | ||
|
6ff2ea6845 | ||
|
b6836db12d | ||
|
4631aea7f5 | ||
|
8b3e9ecfe1 | ||
|
00dcd7ce61 | ||
|
9b7c1387f9 | ||
|
da69bb7d20 | ||
|
7edc627505 | ||
|
34b7c1c74f | ||
|
80763b4efb | ||
|
6a4f0575c4 | ||
|
d391d35e26 | ||
|
5f6e75fe93 | ||
|
5fae666b70 | ||
|
377e46a31f | ||
|
f589fa2d00 | ||
|
c23fdee88f | ||
|
707399057e | ||
|
ce7978a572 | ||
|
5ae484fdaa | ||
|
8dd3e12824 | ||
|
1a4917c874 | ||
|
e27a7a081c | ||
|
3a8acc5ef4 | ||
|
4374f118b4 | ||
|
443f01769c | ||
|
3ea18fcade | ||
|
38bb93fa4f | ||
|
1e203f4e87 | ||
|
5824e7489c | ||
|
02df9d134f | ||
|
ac320b21f4 | ||
|
82f40d7dc6 | ||
|
28ad92e101 | ||
|
9e0bd57ecc | ||
|
044af8bf74 | ||
|
2db79a871a | ||
|
5f435b9614 | ||
|
9b03f6201f | ||
|
111f00adaa | ||
|
002d2090c2 | ||
|
3c1f1a60a3 | ||
|
999ba40bba | ||
|
48e188b0da | ||
|
c41817c704 | ||
|
ecb57cf7ab | ||
|
aa488bf82c | ||
|
b7808adee5 | ||
|
0585fb3253 | ||
|
136a123a56 | ||
|
50d6e2b069 | ||
|
ecc7952340 | ||
|
4fe64a99fd | ||
|
036ea72b30 | ||
|
cd44d3ae67 | ||
|
e5d3e9144d | ||
|
0476d696de | ||
|
acf4723c17 | ||
|
c661dd60d7 | ||
|
a39a39c903 | ||
|
c3913dbc88 | ||
|
9b68e3095e | ||
|
e223d08bbc | ||
|
e42401206b | ||
|
15c39fde7f | ||
|
e284de79a8 | ||
|
50f44fb84c | ||
|
29af46fa28 | ||
|
dc86cfacd8 | ||
|
70d35e5fd5 | ||
|
245dfaa6e1 | ||
|
bcb1e0ef9d | ||
|
f764bcb627 | ||
|
5f6205c150 | ||
|
78681df65f | ||
|
d889cdf2b7 | ||
|
4e6496adc0 | ||
|
fd1bc9ee00 | ||
|
3bb6d089fe | ||
|
7248750277 | ||
|
6cace107e5 | ||
|
3042894e13 | ||
|
4b6fb7beed | ||
|
061b304aa8 | ||
|
71e9e33fd7 | ||
|
b57edf9bf5 | ||
|
83cfbd4980 | ||
|
959e49b01b | ||
|
08a3fbf704 | ||
|
4dd36ed9c4 | ||
|
b1ea926aa6 | ||
|
bd39dac6ec | ||
|
fbd764c76f | ||
|
d9dee949ef | ||
|
f7d3ba2427 | ||
|
4b36baad92 | ||
|
b99093b1f4 | ||
|
121353ae3d | ||
|
af29690c63 | ||
|
2fb627a6e9 | ||
|
f11e37374b | ||
|
3560616b52 | ||
|
80219fa10b | ||
|
c5361c07ef | ||
|
6a11838003 | ||
|
a62abbf399 | ||
|
dd95dece87 | ||
|
c938122f7e | ||
|
3887da26d0 | ||
|
7af193f770 | ||
|
ca654b02bd | ||
|
d46a79097a | ||
|
a92fd943e3 | ||
|
d6093394d8 | ||
|
f1537e305a | ||
|
1847ef4363 | ||
|
0fd695c8bc | ||
|
ae083a7992 | ||
|
c71d4e6b57 | ||
|
304530a58a | ||
|
2df67a1075 | ||
|
3664d0920b | ||
|
9728511d75 | ||
|
fd72608dd4 | ||
|
065dc1c71e | ||
|
c1dbad14ec | ||
|
80fe789b9d | ||
|
d1359b91a3 | ||
|
6367405870 | ||
|
84dcf8cea8 | ||
|
b43a05c03c | ||
|
ae27906e3b | ||
|
6dd00094eb | ||
|
57e32f397f | ||
|
d357e0c582 | ||
|
dd8b74b096 | ||
|
4ef52c2c02 | ||
|
033ff64139 | ||
|
532de654e2 | ||
|
9e7b7ea25a | ||
|
a950bc36c3 | ||
|
9b0e19049d | ||
|
ddbaa7b6cc | ||
|
268085f37a | ||
|
9c28c451e4 | ||
|
04fc9ca757 | ||
|
f607bae96e | ||
|
d94e777dde | ||
|
94e38f751a | ||
|
299b8a3957 | ||
|
b27a7627b5 | ||
|
d7b23c6f00 | ||
|
463121c23e | ||
|
460dae64e3 | ||
|
a73493a042 | ||
|
a24eeaccc8 | ||
|
c93170119f | ||
|
e86e1ece9c | ||
|
9f240d9595 | ||
|
0877003cdf | ||
|
3df4ec5cf7 | ||
|
a119a86e78 | ||
|
9eaacfff8d | ||
|
0a314a22f1 | ||
|
d0b3e069d9 | ||
|
6a17e6f29f | ||
|
0fd6af8ed0 | ||
|
797cfbd57f | ||
|
29b225c1eb | ||
|
1cecd22213 | ||
|
35005ea725 | ||
|
3fff508728 | ||
|
625bee14ef | ||
|
fd6126f0c1 | ||
|
b6e36365f2 | ||
|
efba35272d | ||
|
e626f57aac | ||
|
938bfafe72 | ||
|
c9eca9c76c | ||
|
a2f97802f2 | ||
|
3120b96d35 | ||
|
d66306f890 | ||
|
ded1d6bf49 | ||
|
05014da6c7 | ||
|
5ff2436b15 | ||
|
b0ebee8633 | ||
|
222154397a | ||
|
b16a1918de | ||
|
9046645006 | ||
|
48270b17ee | ||
|
38865a6069 | ||
|
b461f2f079 | ||
|
603c09eeb1 | ||
|
e298910b4b | ||
|
d4b385f5a2 | ||
|
bd45821dae | ||
|
8e2a6a3d47 | ||
|
35bcbb7a06 | ||
|
80b0ee0460 | ||
|
a985063032 | ||
|
8325a649d7 | ||
|
85978fc0a2 | ||
|
865a4c1c0f | ||
|
0570725353 | ||
|
689b9b7926 | ||
|
c6b0b260ef | ||
|
9c385b11a7 | ||
|
eff72bee91 | ||
|
16dc11bb88 | ||
|
85c23e673b | ||
|
5cb8f71a1e | ||
|
0847461f35 | ||
|
e9066ffbf8 | ||
|
fca58c279d | ||
|
bbb22f8438 | ||
|
f1a0d5c9b5 | ||
|
9f58d025d0 | ||
|
27bc59354f | ||
|
23cd59bbac | ||
|
5b02b0379f | ||
|
f0ea8bf52e | ||
|
212a7e57a8 | ||
|
e8c4bf3406 | ||
|
5504a3fae8 | ||
|
0033bb2bdd | ||
|
79e1132bc7 | ||
|
aecdfd1054 | ||
|
61fbc0e2fb | ||
|
4b1d888845 | ||
|
377f22c693 | ||
|
743ef4aef7 | ||
|
d9e25b39af | ||
|
47cb481682 | ||
|
13889cfd2a | ||
|
dca25ac784 | ||
|
c5bde173a0 | ||
|
a1e9621195 | ||
|
731dd41de1 | ||
|
5cca961668 | ||
|
df3d3a3caf | ||
|
18cbd059be | ||
|
3a0126c74c | ||
|
2d035a91e3 | ||
|
9c5e7db748 | ||
|
3ff522cff2 | ||
|
f0d89970ee | ||
|
a4ed6368db | ||
|
1b67b4d93d | ||
|
f1b2d39f1f | ||
|
c3e9b480bd | ||
|
e879c88e87 | ||
|
f92e685ca6 | ||
|
7fe491f50f | ||
|
728f89f109 | ||
|
f3ca37d7cd | ||
|
86722c5c55 | ||
|
7c85bc266b | ||
|
c810f934c6 | ||
|
27c5de72cc | ||
|
0a66ad8bbe | ||
|
14798b1660 | ||
|
04caa38112 | ||
|
2d21d4989e | ||
|
97a24727d1 | ||
|
9f6b1493d4 | ||
|
50aacbed11 | ||
|
5c48725110 | ||
|
19f6457d6d | ||
|
ea0c0cf027 | ||
|
43777b5989 | ||
|
144eb7a39c | ||
|
d0dc072324 | ||
|
fd11648d98 | ||
|
c43d423aa3 | ||
|
3c72dd7098 | ||
|
086eb5ab8e | ||
|
0a8934a6cf | ||
|
d5ae61d481 | ||
|
74404eb0c6 | ||
|
5026fb3b4d | ||
|
78d5d9977b | ||
|
5c85d80f81 | ||
|
1f4bec8eb2 | ||
|
10c7646fb1 | ||
|
c0f4721d49 | ||
|
44179984e5 | ||
|
751b015c04 | ||
|
79dde803b4 | ||
|
961163305a | ||
|
8a0f396810 | ||
|
b5de0fb940 | ||
|
6e1189afc4 | ||
|
dd6fb4df85 | ||
|
f6bec8b78c | ||
|
b951f92ff1 | ||
|
e5840fe0f4 | ||
|
ad0eae7d62 | ||
|
c04499a353 | ||
|
257feba5bd | ||
|
72326403a0 | ||
|
313625577c | ||
|
f982e1b01a | ||
|
60d68e059c | ||
|
3cdb93bfc4 | ||
|
7ace00c139 | ||
|
876eb01506 | ||
|
2cb95d8a1a | ||
|
643cbbef9b | ||
|
710dbe00b6 | ||
|
4d47201ce3 | ||
|
165673a998 | ||
|
31a4823b54 | ||
|
41a2380791 | ||
|
d491835ef1 | ||
|
9dca440d91 | ||
|
2779eb9d5f | ||
|
7b5754514c | ||
|
da67593e27 | ||
|
3c05657fe0 | ||
|
e45d2504e6 | ||
|
ced7f41af2 | ||
|
097c1343be | ||
|
f34ee11df8 | ||
|
5753b1c28f | ||
|
76e618bbea | ||
|
e59824c97b | ||
|
c4fdcddf0a | ||
|
49a9de1a05 | ||
|
52559865ca | ||
|
a4075c4728 | ||
|
7a5cf227c4 | ||
|
be82337924 | ||
|
9b0d354683 | ||
|
3bd408e551 | ||
|
c810acae4c | ||
|
077df4ee28 | ||
|
6000c438da | ||
|
15ba1ef120 | ||
|
a2849a9758 | ||
|
345528e4b3 | ||
|
1e8fe818bf | ||
|
cf1f20f867 | ||
|
788aa857a0 | ||
|
2248cfdc35 | ||
|
e9c9d9f451 | ||
|
73066348ea | ||
|
8d0f0a329c | ||
|
36e76ef080 | ||
|
b639a9e50a | ||
|
df189215eb | ||
|
05d811aa4e | ||
|
ba1c87fc3e | ||
|
970ff2145e | ||
|
fab6590ac7 | ||
|
ccd1a2b568 | ||
|
2b952c5a5f | ||
|
f380ba4484 | ||
|
43d6b2cbf7 | ||
|
aa0aea352b | ||
|
8ad6609527 | ||
|
2dd6612e45 | ||
|
ea32f72313 | ||
|
5953031bee | ||
|
f5600631f7 | ||
|
573ae347ed | ||
|
9dbe79593e | ||
|
b5699b85f1 | ||
|
e8ea6cdd5d | ||
|
7d1fcab6b4 | ||
|
1a9770d390 | ||
|
db7d86851a | ||
|
043016e08d | ||
|
6f95e3c2b7 | ||
|
def0268d6e | ||
|
23d4b2b42b | ||
|
2ab25a402b | ||
|
ab8d85be00 | ||
|
128748d33e | ||
|
bc59f9ff3d | ||
|
7ddb6bf93b | ||
|
c4f0c9d267 | ||
|
b4ddefb990 | ||
|
4c1e60c71d | ||
|
63bf471b63 | ||
|
639347806b | ||
|
6087d8f4dc | ||
|
efcbff8d62 | ||
|
22f6bd795e | ||
|
e13a9c8184 | ||
|
dd12afcce0 | ||
|
b1a93a6e49 | ||
|
afab075808 | ||
|
746f450a89 | ||
|
7f4265892d | ||
|
a3444c334a | ||
|
cd73bf8282 | ||
|
8a0c6d3631 | ||
|
fe04a2973e | ||
|
fe1159a8f5 | ||
|
08aa6abcc8 | ||
|
1270058e99 | ||
|
5a20dc5837 | ||
|
78a6684f53 | ||
|
f66add9b6a | ||
|
16aaf55a91 | ||
|
5636a917ef | ||
|
91f1d59b7c | ||
|
1eb5b9cffe | ||
|
d9451b7a74 | ||
|
516cd70bba | ||
|
29ed01182e | ||
|
e704153010 | ||
|
08fee6d1ec | ||
|
c3a774e1cb | ||
|
584d3faa1a | ||
|
5b7dae6586 | ||
|
16926cdaf1 | ||
|
26c89575d8 | ||
|
f26442f611 | ||
|
92ffc545de | ||
|
88202b7cc9 | ||
|
34ffcc989e | ||
|
42c2460718 | ||
|
8374ec9564 | ||
|
de37908d05 | ||
|
5c96b83455 | ||
|
9366ac60f2 | ||
|
4fe8d78099 | ||
|
83f5760126 | ||
|
02af1c7512 | ||
|
c15980b32a | ||
|
c81447e2ef | ||
|
1445f6a5f4 | ||
|
45d46082f2 | ||
|
23aa0f179e | ||
|
7211e6981c | ||
|
f1b1789207 | ||
|
c9e4b7eb0b | ||
|
91b2bdb4ac | ||
|
87bb54b7c5 | ||
|
af94ab6dd0 | ||
|
aefe37068b | ||
|
762760545d | ||
|
25433c0570 | ||
|
d9e885416a | ||
|
cc0f17f722 | ||
|
ef740e23db | ||
|
bf4f296fe1 | ||
|
acb468fd36 | ||
|
a7d2ddef1a | ||
|
c577cbc933 | ||
|
ff06d4dfec | ||
|
a6e2ee698a | ||
|
7cf3a5afe8 | ||
|
15dab2549a | ||
|
c4d6bb5d70 | ||
|
3e0d1eaaa1 | ||
|
db054ccdcc | ||
|
a9e0ce57d3 | ||
|
7af79df7c4 | ||
|
3bceaea045 | ||
|
bd9772222a | ||
|
a42a183302 | ||
|
fa2c3f18ce | ||
|
2b6ce8b3ae | ||
|
270882253d | ||
|
a5df30d441 | ||
|
dbffd6ff66 | ||
|
3102dab50d | ||
|
73ac2ba2cb | ||
|
711a5b65b6 | ||
|
8e6e6f40a3 | ||
|
6fe436665b | ||
|
675d4ff780 | ||
|
808699b238 | ||
|
01ad90e905 | ||
|
e91e8c02a6 | ||
|
b2dd3d1694 | ||
|
6a3be051e4 | ||
|
62413b37ba | ||
|
9a5d3a0067 | ||
|
4d18f6fa5a | ||
|
56d48078b6 | ||
|
c9edd2a906 | ||
|
dac717673d | ||
|
aa0622b940 | ||
|
50af2e726c | ||
|
9c8c54799f | ||
|
9e1c648a7c | ||
|
130338b9a5 | ||
|
6744c52087 | ||
|
a853c56994 | ||
|
41b6d0b63b | ||
|
87e956493e | ||
|
14e4620c5c | ||
|
c563c537f4 | ||
|
bc15dfc679 | ||
|
3d380dc88c | ||
|
e934c7a3ba | ||
|
35ee109cd3 | ||
|
0fa2562129 | ||
|
db651f5f1d | ||
|
9e958a5f9d | ||
|
a7f7556a6d | ||
|
bb7e36cc85 | ||
|
1fd3ef7eeb | ||
|
4f8b6d56c9 | ||
|
8abb393c3e | ||
|
c51a608a28 | ||
|
6569e5c3df | ||
|
635346bff6 | ||
|
0ae10c6c42 | ||
|
293ee90c8a | ||
|
5607b57bd1 | ||
|
6413fcd33c | ||
|
9ddf1a3c20 | ||
|
9b221f4583 | ||
|
657e5212f4 | ||
|
0804ac5e96 | ||
|
574add6956 | ||
|
52738f4783 | ||
|
c53cbb1ce2 | ||
|
aef4ce6296 | ||
|
d51a22e030 | ||
|
c258cc7d0d | ||
|
11a78eccbc | ||
|
c0c60f2f2f | ||
|
c497d71757 | ||
|
3a41a656ac | ||
|
dc36339faa | ||
|
a37285b5cf | ||
|
3bcb0f10e4 | ||
|
20be1fdfd6 | ||
|
e4710bbabc | ||
|
673829298b | ||
|
03f00c7d37 | ||
|
f7e5297589 | ||
|
06513b3bfe | ||
|
62198eac33 | ||
|
80b99a65ed | ||
|
52c30ec9d1 | ||
|
7127a46543 | ||
|
69da9e1936 | ||
|
4cd70b1815 | ||
|
5e5278aef8 | ||
|
2b41ef578a | ||
|
e76745e52e | ||
|
6fd8defc9a | ||
|
9e04764444 | ||
|
cb0c852933 | ||
|
0929d93342 | ||
|
43010fcb64 | ||
|
234cc5518c | ||
|
2ba2eebbaa | ||
|
0045ecf91e | ||
|
130880cf87 | ||
|
2d8f70f09a | ||
|
5d925b65c9 | ||
|
30bd8d1cf3 | ||
|
1c4f86c7ef | ||
|
695a4b9ecb | ||
|
dab2bbac0c | ||
|
edbec45660 | ||
|
bb4169f4bc | ||
|
3dbf65b62a | ||
|
7a1991f56c | ||
|
e549a0546e | ||
|
ce28a0e51d | ||
|
8d85680fce | ||
|
df1c75f56a | ||
|
d7389eef47 | ||
|
1416cd9d43 | ||
|
805a871146 | ||
|
9a6ce6b7c3 | ||
|
c96d3952d0 | ||
|
57166fe250 | ||
|
031a05e549 | ||
|
8b4dde9042 | ||
|
c7ab08f01d | ||
|
4f5f216296 | ||
|
df17877ede | ||
|
8d54beee58 | ||
|
34006556c8 | ||
|
92ec1b14c5 | ||
|
02bdb93bbd | ||
|
6144cdcd3a | ||
|
99c8827eb8 | ||
|
e8b9dfb3c3 | ||
|
bc4b5527eb | ||
|
8da4488106 | ||
|
9bd85d7b6f | ||
|
76748cf0b2 | ||
|
8af6e89675 | ||
|
b8f0801112 | ||
|
090734c0c3 | ||
|
35836cdc56 | ||
|
45b407765b | ||
|
59ae1d9830 | ||
|
f2d616cd2f | ||
|
416e184a59 | ||
|
63b549212e | ||
|
129aac2c12 | ||
|
6160622ccd | ||
|
19d6eef747 | ||
|
12b33b29ce | ||
|
b9a5c4927e | ||
|
92d7513e3d | ||
|
711537c732 | ||
|
99490cfd0b | ||
|
13810236d4 | ||
|
8d8b66a7fe | ||
|
f4e51757e5 | ||
|
f7714eeda4 | ||
|
111e537ea2 | ||
|
d34e4b8ed6 | ||
|
431e61d2a5 | ||
|
6e07225639 | ||
|
7875c19a3c | ||
|
8c3f64d0aa | ||
|
074a6d9f1e | ||
|
988a1a6b58 | ||
|
620cedb8c3 | ||
|
8199a07674 | ||
|
d6a230a2dc | ||
|
675323fb69 | ||
|
95ddd0a1dc | ||
|
8aaead0245 | ||
|
801ece4bdd | ||
|
8135c439b0 | ||
|
cb418af07c | ||
|
2f4b8e23fe | ||
|
4657e5b691 | ||
|
48adc7ad4a | ||
|
11e1df01ed | ||
|
6a43803d92 | ||
|
c8a3c64fda | ||
|
5017ed9f7f | ||
|
707e4400f7 | ||
|
ce7fe5b45f | ||
|
24981655bb | ||
|
2d83f74904 | ||
|
58401624c0 | ||
|
71eaefefbf | ||
|
3599884789 | ||
|
af7faebb06 | ||
|
272b666642 | ||
|
e3140d0b87 | ||
|
1ea3d72a1c | ||
|
74aefcd2b1 | ||
|
cc50a025cf | ||
|
63f2263797 | ||
|
9a2822cecb | ||
|
43d9c798b5 | ||
|
9236c15245 | ||
|
508d35cc21 | ||
|
6646471e00 | ||
|
579885393b | ||
|
851bbabd71 | ||
|
cf8b0402a9 | ||
|
7931200b36 | ||
|
c2dab381e5 | ||
|
72005865f3 | ||
|
a4e7a59e17 | ||
|
9ff8fca3f4 | ||
|
ddefb47bc0 | ||
|
4c6997a012 | ||
|
24eb819a85 | ||
|
1f6f9f0f2d | ||
|
4830768e9c | ||
|
5f67294aa5 | ||
|
4ffb5adfed | ||
|
6eda6fa83f | ||
|
ceb279d8fb | ||
|
1c85d22ed8 | ||
|
31575c599d | ||
|
7ab78c95dc | ||
|
4d60d96180 | ||
|
22f62949ae | ||
|
3a638f4d07 | ||
|
28f4fc8880 | ||
|
c83bd1ca6a | ||
|
cbb01617c5 | ||
|
82c27bb541 | ||
|
91528c5510 | ||
|
f7d1949472 | ||
|
e99b4f7e1a | ||
|
5ba7ab03ad | ||
|
9dbddad6e4 | ||
|
59f023e933 | ||
|
f507c44959 | ||
|
6d8b09ba3d | ||
|
249efb5e32 | ||
|
08adcd5758 | ||
|
c7c952f27c | ||
|
897f906631 | ||
|
8714ae80a4 | ||
|
b8f66e44ea | ||
|
a8f331b2bb | ||
|
21d5faed6e | ||
|
4986a39433 | ||
|
18415d96c4 | ||
|
f5303fa504 | ||
|
fe1bf59d6f | ||
|
161cd45fa1 | ||
|
6ef0f172ec | ||
|
b006d9aa9f | ||
|
21e04f3027 | ||
|
af35d47c4e | ||
|
66aebb04e8 | ||
|
0d7e5ba6ae | ||
|
940b8e9dfc | ||
|
ecaf761b61 | ||
|
3f66a24a60 | ||
|
0e9763b055 | ||
|
ddf2c49312 | ||
|
aa20f3a1e0 | ||
|
c49410f040 | ||
|
5dc5c09306 | ||
|
399365be41 | ||
|
603bf4e9ce | ||
|
0f04b73114 | ||
|
6191740d02 | ||
|
fd30aaecf4 | ||
|
0298d48f8d | ||
|
3eb8ddcbc4 | ||
|
f64cd08ec9 | ||
|
043e383498 | ||
|
06824a33cf | ||
|
7d94c61586 | ||
|
fd902bfad3 | ||
|
0842c3c5db | ||
|
f6b029a843 | ||
|
8d2560c74c | ||
|
beba00b24c | ||
|
f3c844b426 | ||
|
de1f8bbfcf | ||
|
d238587f5f | ||
|
9bb9bdd7cf | ||
|
4c04d0d2bf | ||
|
aace9f8c27 | ||
|
a6dc7e1ddc | ||
|
16309d571a | ||
|
d893138250 | ||
|
1f0945446a | ||
|
1766e374cd |
14
.cursor/mcp.json
Normal file
14
.cursor/mcp.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"console-ninja": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"~/.console-ninja/mcp/"
|
||||
]
|
||||
},
|
||||
"context7": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@upstash/context7-mcp@latest"]
|
||||
}
|
||||
}
|
||||
}
|
11
.cursor/rules/ai-sdk-best-practices.mdc
Normal file
11
.cursor/rules/ai-sdk-best-practices.mdc
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
description: Best practices for using Vercel AI SDK
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use the `createClient` function to initialize your OpenAI client.
|
||||
- Implement proper error handling and rate limiting for API requests.
|
||||
- Utilize streaming responses for better user experience in long-running tasks.
|
||||
- Leverage the `ai` package for easy integration with React components.
|
||||
- Follow OpenAI's guidelines for responsible AI usage and data privacy
|
43
.cursor/rules/database-state-management.mdc
Normal file
43
.cursor/rules/database-state-management.mdc
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
description:
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
# Database and State Management Guide
|
||||
|
||||
## Database (Drizzle ORM)
|
||||
- Schema definitions in `src/db/schema.ts`
|
||||
- Migrations in `src/db/migrations`
|
||||
- Use `db:generate` to create new migration files based on schema changes
|
||||
- Use `db:migrate` to apply pending migrations to the database
|
||||
- Use `db:push` to sync schema changes directly to the database (development only)
|
||||
- Use `db:studio` to view and manage database data through the Drizzle Studio UI
|
||||
- Follow naming conventions for tables and columns
|
||||
- Use proper data types and constraints
|
||||
- Implement proper indexes
|
||||
- Handle relationships properly
|
||||
- Use transactions when needed
|
||||
|
||||
## State Management (Zustand)
|
||||
- Store definitions in `src/stores/`
|
||||
- Keep stores modular and focused
|
||||
- Use TypeScript for store types
|
||||
- Implement proper state updates
|
||||
- Handle async operations properly
|
||||
- Use selectors for derived state
|
||||
- Implement proper error handling
|
||||
- Use middleware when needed
|
||||
- Keep store logic pure
|
||||
- Document complex state logic
|
||||
|
||||
## Data Flow
|
||||
1. Server-side data fetching in server components
|
||||
2. Client-side state in Zustand stores
|
||||
3. Form state in React Hook Form
|
||||
4. API calls through server actions
|
||||
5. Database operations through Drizzle
|
||||
6. File storage through AWS S3
|
||||
7. Proper error handling at each layer
|
||||
8. Type safety throughout
|
||||
9. Proper validation with Zod
|
||||
10. Proper caching strategies
|
10
.cursor/rules/date-fns-best-practices.mdc
Normal file
10
.cursor/rules/date-fns-best-practices.mdc
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Best practices for date and time manipulation with date-fns
|
||||
globs: *.ts,*.tsx
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use the `format` function for consistent date formatting across your application.
|
||||
- Implement proper timezone handling using the `utcToZonedTime` function.
|
||||
- Utilize the `intervalToDuration` function for calculating time differences.
|
||||
- Leverage the `isWithinInterval` function for date range checks.
|
39
.cursor/rules/development-workflow.mdc
Normal file
39
.cursor/rules/development-workflow.mdc
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
description:
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
# Development Workflow Guide
|
||||
|
||||
## Available Scripts
|
||||
- `pnpm dev`: Start development server with content collections
|
||||
- `pnpm build`: Build the application and content collections
|
||||
- `pnpm start`: Start production server
|
||||
- `pnpm lint`: Run Biome linter
|
||||
- `pnpm format`: Format code with Biome
|
||||
- `pnpm db:generate`: Generate new migration files based on schema changes
|
||||
- `pnpm db:migrate`: Apply pending migrations to the database
|
||||
- `pnpm db:push`: Sync schema changes directly to the database (development only)
|
||||
- `pnpm db:studio`: Open Drizzle Studio for database inspection and management
|
||||
- `pnpm email`: Start email template development server
|
||||
|
||||
## Development Process
|
||||
1. Use TypeScript for all new code
|
||||
2. Follow Biome formatting rules
|
||||
3. Write server actions in `src/actions/`
|
||||
4. Use Zustand for client-side state
|
||||
5. Implement database changes through Drizzle migrations
|
||||
6. Use Radix UI components for consistent UI
|
||||
7. Follow the established directory structure
|
||||
8. Write tests for new features
|
||||
9. Update content collections when adding new content
|
||||
10. Use environment variables from `env.example`
|
||||
|
||||
## Code Style
|
||||
- Use functional components with hooks
|
||||
- Implement proper error handling
|
||||
- Follow TypeScript best practices
|
||||
- Use proper type definitions
|
||||
- Document complex logic
|
||||
- Keep components small and focused
|
||||
- Use proper naming conventions
|
10
.cursor/rules/drizzle-orm-best-practices.mdc
Normal file
10
.cursor/rules/drizzle-orm-best-practices.mdc
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Best practices for using Drizzle ORM with database
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use Drizzle's type-safe query builder for better code completion and safety.
|
||||
- Implement migrations using Drizzle Kit for database schema management.
|
||||
- Utilize Drizzle's relation system to define and query relationships.
|
||||
- Use Drizzle's transaction API for complex, atomic operations.
|
11
.cursor/rules/nextjs-best-practices.mdc
Normal file
11
.cursor/rules/nextjs-best-practices.mdc
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
description: Best practices for Next.js applications and routing
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Utilize Next.js 15's new features like Server Actions for improved performance and security
|
||||
- Implement proper error handling with `error.tsx` and `not-found.tsx` for better user experience
|
||||
- Use `next-safe-action` for secure form submissions and API calls
|
||||
- Use the `use client` directive for client components to optimize server-side rendering
|
||||
- Leverage `next-themes` for easy theme management and dark mode support
|
37
.cursor/rules/project-structure.mdc
Normal file
37
.cursor/rules/project-structure.mdc
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
description:
|
||||
globs: **/*.{ts,tsx}
|
||||
alwaysApply: false
|
||||
---
|
||||
# Project Structure Guide
|
||||
|
||||
## Core Directories
|
||||
- `src/app/`: Next.js app router pages and layouts
|
||||
- `src/components/`: Reusable React components
|
||||
- `src/lib/`: Utility functions and shared code
|
||||
- `src/db/`: Database schema and migrations using Drizzle ORM
|
||||
- `src/stores/`: Zustand state management
|
||||
- `src/actions/`: Server actions and API routes
|
||||
- `src/hooks/`: Custom React hooks
|
||||
- `src/types/`: TypeScript type definitions
|
||||
- `src/i18n/`: Internationalization setup
|
||||
- `src/mail/`: Email templates and mail functionality
|
||||
- `src/payment/`: Payment integration
|
||||
- `src/analytics/`: Analytics and tracking
|
||||
- `src/storage/`: File storage integration
|
||||
- `src/notification/`: Sending Notifications
|
||||
|
||||
## Configuration Files
|
||||
- `next.config.ts`: Next.js configuration
|
||||
- `drizzle.config.ts`: Database configuration
|
||||
- `biome.json`: Code formatting and linting rules
|
||||
- `tsconfig.json`: TypeScript configuration
|
||||
- `components.json`: UI components configuration
|
||||
|
||||
## Content Management
|
||||
- `content/`: MDX content files
|
||||
- `source.config.ts`: Fumadocs source configuration
|
||||
|
||||
## Environment
|
||||
- `env.example`: Environment variables template
|
||||
- `global.d.ts`: Global TypeScript declarations
|
11
.cursor/rules/radix-ui-best-practices.mdc
Normal file
11
.cursor/rules/radix-ui-best-practices.mdc
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
description: Best practices for using Radix UI components
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use Radix UI primitives for building custom, accessible components
|
||||
- Utilize Radix UI's composition patterns for creating complex, reusable UI elements
|
||||
- Implement proper ARIA attributes and keyboard navigation for accessibility
|
||||
- Utilize Radix UI's built-in state management for complex components
|
||||
- Customize Radix UI components using the `asChild` prop for better flexibility
|
12
.cursor/rules/react-best-practices.mdc
Normal file
12
.cursor/rules/react-best-practices.mdc
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
description: Best practices for React component development
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use functional components with hooks instead of class components for better performance and readability
|
||||
- Implement proper state management using using libraries like Zustand for complex state scenarios
|
||||
- Utilize React 19's new features like `use` hook for better data fetching and suspense integration
|
||||
- Ensure proper prop type validation using TypeScript for enhanced type safety
|
||||
- Utilize `useCallback` and `useMemo` for performance optimization
|
||||
- Leverage `react-hook-form` for efficient form handling and validation
|
10
.cursor/rules/react-hook-form-best-practices.mdc
Normal file
10
.cursor/rules/react-hook-form-best-practices.mdc
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Best practices for form handling with React Hook Form
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use the `useForm` hook for efficient form state management.
|
||||
- Implement validation using Zod with `@hookform/resolvers` for type-safe form validation.
|
||||
- Utilize the `Controller` component for integrating with custom inputs.
|
||||
- Leverage the `useFormContext` hook for sharing form state across components.
|
11
.cursor/rules/stripe-best-practices.mdc
Normal file
11
.cursor/rules/stripe-best-practices.mdc
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
description: Best practices for integrating Stripe payments
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use the `@stripe/stripe-js` package for client-side Stripe integration.
|
||||
- Implement proper error handling and user feedback for payment flows.
|
||||
- Utilize Stripe's Elements for secure, customizable payment inputs.
|
||||
- Leverage Stripe's Webhooks for real-time payment status updates.
|
||||
- Follow Stripe's best practices for PCI compliance and security
|
12
.cursor/rules/tailwindcss-best-practices.mdc
Normal file
12
.cursor/rules/tailwindcss-best-practices.mdc
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
description: Best practices for styling with Tailwind CSS
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use utility-first approach for rapid development and maintainability
|
||||
- Implement responsive design using Tailwind's built-in breakpoints
|
||||
- Utilize the `@apply` directive for creating custom utility classes
|
||||
- Leverage Tailwind's JIT mode for improved performance and smaller bundle sizes
|
||||
- Utilize `tailwind-merge` for efficient class merging and overriding
|
||||
- Leverage `tailwindcss-animate` for easy animation implementation
|
14
.cursor/rules/typescript-best-practices.mdc
Normal file
14
.cursor/rules/typescript-best-practices.mdc
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
description: TypeScript coding standards and type safety guidelines
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Enable strict mode in your `tsconfig.json` for better type checking.
|
||||
- Use interfaces for object shapes and types for unions or intersections.
|
||||
- Leverage type inference where possible to reduce type annotations.
|
||||
- Use generics for reusable components and functions.
|
||||
- Use strict null checks to prevent null and undefined errors
|
||||
- Implement proper type inference using generics for reusable components.
|
||||
- Utilize type guards and assertions for runtime type checking.
|
||||
- Use `pnpm` as default package manager if run Command in Terminal.
|
54
.cursor/rules/ui-components.mdc
Normal file
54
.cursor/rules/ui-components.mdc
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
description:
|
||||
globs: **/*.{ts,tsx}
|
||||
alwaysApply: false
|
||||
---
|
||||
# UI and Components Guide
|
||||
|
||||
## Component Structure
|
||||
- Components in `src/components/`
|
||||
- Follow atomic design principles
|
||||
- Use Radix UI primitives
|
||||
- Implement proper accessibility
|
||||
- Use Tailwind CSS for styling
|
||||
- Follow consistent naming
|
||||
- Keep components focused
|
||||
- Implement proper error states
|
||||
- Handle loading states
|
||||
- Use proper TypeScript types
|
||||
|
||||
## UI Libraries
|
||||
- Radix UI for primitives
|
||||
- Tailwind CSS for styling
|
||||
- Framer Motion for animations
|
||||
- React Hook Form for forms
|
||||
- Zod for validation
|
||||
- Lucide React for icons
|
||||
- Tabler Icons for additional icons
|
||||
- Sonner for toasts
|
||||
- Vaul for drawers
|
||||
- Embla Carousel for carousels
|
||||
|
||||
## Styling Guidelines
|
||||
- Use Tailwind CSS classes
|
||||
- Follow design system tokens
|
||||
- Implement dark mode support
|
||||
- Use proper spacing scale
|
||||
- Follow color palette
|
||||
- Implement responsive design
|
||||
- Use proper typography
|
||||
- Handle hover/focus states
|
||||
- Implement proper transitions
|
||||
- Use proper z-index scale
|
||||
|
||||
## Accessibility
|
||||
- Use semantic HTML
|
||||
- Implement proper ARIA labels
|
||||
- Handle keyboard navigation
|
||||
- Support screen readers
|
||||
- Use proper color contrast
|
||||
- Implement focus management
|
||||
- Handle dynamic content
|
||||
- Support reduced motion
|
||||
- Test with assistive tools
|
||||
- Follow WCAG guidelines
|
10
.cursor/rules/zod-best-practices.mdc
Normal file
10
.cursor/rules/zod-best-practices.mdc
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Best practices for schema validation with Zod
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Define clear and reusable schemas for data validation
|
||||
- Use Zod's type inference for TypeScript integration and type safety
|
||||
- Implement custom validation rules using Zod's `refine` method
|
||||
- Utilize Zod with `react-hook-form` for seamless form validation
|
10
.cursor/rules/zustand-best-practices.mdc
Normal file
10
.cursor/rules/zustand-best-practices.mdc
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
description: Best practices for state management with Zustand
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use the `create` function to define your store for simplicity and performance.
|
||||
- Implement middleware like `persist` for persisting state across sessions.
|
||||
- Utilize the `useStore` hook for accessing store state in components.
|
||||
- Leverage the `immer` middleware for easier state updates with mutable syntax.
|
16
.dockerignore
Normal file
16
.dockerignore
Normal file
@ -0,0 +1,16 @@
|
||||
.cursor
|
||||
.claude
|
||||
.conductor
|
||||
.kiro
|
||||
.github
|
||||
.next
|
||||
.open-next
|
||||
.source
|
||||
.vscode
|
||||
.git
|
||||
.wrangler
|
||||
.dockerignore
|
||||
node_modules
|
||||
**/node_modules
|
||||
Dockerfile
|
||||
LICENSE
|
25
.editorconfig
Normal file
25
.editorconfig
Normal file
@ -0,0 +1,25 @@
|
||||
# EditorConfig helps maintain consistent coding styles across different editors and IDEs
|
||||
# Visit https://editorconfig.org/ for more information
|
||||
# Top-most EditorConfig file, no other .editorconfig files should be read in parent directories
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md,*.mdx]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.js,*.ts]
|
||||
quote_type = single
|
||||
|
||||
[{*.c,*.cc,*.h,*.hh,*.cpp,*.hpp,*.m,*.mm,*.mpp,*.js,*.java,*.go,*.rs,*.php,*.ng,*.jsx,*.ts,*.d,*.cs,*.swift}]
|
||||
curly_bracket_next_line = false
|
||||
spaces_around_operators = true
|
||||
spaces_around_brackets = outside
|
||||
indent_brace_style = K&R
|
41
.gitattributes
vendored
Normal file
41
.gitattributes
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# Set default behavior to automatically normalize line endings
|
||||
* text=auto
|
||||
|
||||
# Force LF line endings for text files
|
||||
*.js text eol=lf
|
||||
*.jsx text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.tsx text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.mdx text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.css text eol=lf
|
||||
*.scss text eol=lf
|
||||
*.html text eol=lf
|
||||
*.xml text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.sh text eol=lf
|
||||
|
||||
# Ensure these files are always treated as text and get LF line endings
|
||||
.gitignore text eol=lf
|
||||
.gitattributes text eol=lf
|
||||
.editorconfig text eol=lf
|
||||
*.config.js text eol=lf
|
||||
*.config.ts text eol=lf
|
||||
|
||||
# Binary files should be left untouched
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.svg binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.ttf binary
|
||||
*.eot binary
|
||||
*.pdf binary
|
||||
*.zip binary
|
||||
*.tar.gz binary
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: javayhu
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone16]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: MkSaaS Community Support
|
||||
url: https://github.com/MkSaaSHQ/mksaas-template/discussions
|
||||
about: Please ask and answer questions here.
|
||||
- name: MkSaaS Documentation
|
||||
url: https://mksaas.com/docs
|
||||
about: Please check out the documentation here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[feat]"
|
||||
labels: enhancement
|
||||
assignees: javayhu
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
26
.gitignore
vendored
26
.gitignore
vendored
@ -30,12 +30,38 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
certificates
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# claude code
|
||||
.claude
|
||||
|
||||
# conductor
|
||||
.conductor
|
||||
|
||||
# kiro
|
||||
.kiro
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# content collections
|
||||
.content-collections
|
||||
|
||||
# fumadocs
|
||||
.source
|
||||
|
||||
# OpenNext build output
|
||||
.open-next
|
||||
|
||||
# wrangler files
|
||||
.wrangler
|
||||
.dev.vars
|
||||
.dev.vars*
|
||||
!.dev.vars.example
|
||||
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"biomejs.biome",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"Lokalise.i18n-ally",
|
||||
"unifiedjs.vscode-mdx",
|
||||
"eamodio.gitlens",
|
||||
"editorconfig.editorconfig"
|
||||
]
|
||||
}
|
35
.vscode/settings.json
vendored
Normal file
35
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"i18n-ally.localesPaths": [
|
||||
"messages",
|
||||
"src/i18n"
|
||||
],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"quickfix.biome": "explicit",
|
||||
"source.organizeImports.biome": "explicit"
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
".next": true,
|
||||
".source": true,
|
||||
".wrangler": true,
|
||||
".open-next": true,
|
||||
".vscode": true,
|
||||
".cursor": true,
|
||||
".claude": true,
|
||||
".conductor": true,
|
||||
".kiro": true,
|
||||
".github": true
|
||||
}
|
||||
}
|
109
CLAUDE.md
Normal file
109
CLAUDE.md
Normal file
@ -0,0 +1,109 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Core Development
|
||||
- `pnpm dev` - Start development server with content collections
|
||||
- `pnpm build` - Build the application and content collections
|
||||
- `pnpm start` - Start production server
|
||||
- `pnpm lint` - Run Biome linter (use for code quality checks)
|
||||
- `pnpm format` - Format code with Biome
|
||||
|
||||
### Database Operations (Drizzle ORM)
|
||||
- `pnpm db:generate` - Generate new migration files based on schema changes
|
||||
- `pnpm db:migrate` - Apply pending migrations to the database
|
||||
- `pnpm db:push` - Sync schema changes directly to the database (development only)
|
||||
- `pnpm db:studio` - Open Drizzle Studio for database inspection and management
|
||||
|
||||
### Content and Email
|
||||
- `pnpm content` - Process MDX content collections
|
||||
- `pnpm email` - Start email template development server on port 3333
|
||||
|
||||
## Project Architecture
|
||||
|
||||
This is a Next.js 15 full-stack SaaS application with the following key architectural components:
|
||||
|
||||
### Core Stack
|
||||
- **Framework**: Next.js 15 with App Router
|
||||
- **Database**: PostgreSQL with Drizzle ORM
|
||||
- **Authentication**: Better Auth with social providers (Google, GitHub)
|
||||
- **Payments**: Stripe integration with subscription and one-time payments
|
||||
- **UI**: Radix UI components with TailwindCSS
|
||||
- **State Management**: Zustand for client-side state
|
||||
- **Internationalization**: next-intl with English and Chinese locales
|
||||
- **Content**: Fumadocs for documentation and MDX for content
|
||||
- **Code Quality**: Biome for formatting and linting
|
||||
|
||||
### Key Directory Structure
|
||||
- `src/app/` - Next.js app router with internationalized routing
|
||||
- `src/components/` - Reusable React components organized by feature
|
||||
- `src/lib/` - Utility functions and shared code
|
||||
- `src/db/` - Database schema and migrations
|
||||
- `src/actions/` - Server actions for API operations
|
||||
- `src/stores/` - Zustand state management
|
||||
- `src/hooks/` - Custom React hooks
|
||||
- `src/config/` - Application configuration files
|
||||
- `src/i18n/` - Internationalization setup
|
||||
- `src/mail/` - Email templates and mail functionality
|
||||
- `src/payment/` - Stripe payment integration
|
||||
- `src/credits/` - Credit system implementation
|
||||
- `content/` - MDX content files for docs and blog
|
||||
- `messages/` - Translation files (en.json, zh.json) for internationalization
|
||||
|
||||
### Authentication & User Management
|
||||
- Uses Better Auth with PostgreSQL adapter
|
||||
- Supports email/password and social login (Google, GitHub)
|
||||
- Includes user management, email verification, and password reset
|
||||
- Admin plugin for user management and banning
|
||||
- Automatic newsletter subscription on user creation
|
||||
|
||||
### Payment System
|
||||
- Stripe integration for subscriptions and one-time payments
|
||||
- Three pricing tiers: Free, Pro (monthly/yearly), and Lifetime
|
||||
- Credit system with packages for pay-per-use features
|
||||
- Customer portal for subscription management
|
||||
|
||||
### Feature Modules
|
||||
- **Blog**: MDX-based blog with pagination and categories
|
||||
- **Docs**: Fumadocs-powered documentation
|
||||
- **AI Features**: Image generation with multiple providers (OpenAI, Replicate, etc.)
|
||||
- **Newsletter**: Email subscription system
|
||||
- **Analytics**: Multiple analytics providers support
|
||||
- **Storage**: S3 integration for file uploads
|
||||
|
||||
### Development Workflow
|
||||
1. Use TypeScript for all new code
|
||||
2. Follow Biome formatting rules (single quotes, trailing commas)
|
||||
3. Write server actions in `src/actions/`
|
||||
4. Use Zustand for client-side state management
|
||||
5. Implement database changes through Drizzle migrations
|
||||
6. Use Radix UI components for consistent UI
|
||||
7. Follow the established directory structure
|
||||
8. Use proper error handling with error.tsx and not-found.tsx
|
||||
9. Leverage Next.js 15 features like Server Actions
|
||||
10. Use `next-safe-action` for secure form submissions
|
||||
|
||||
### Configuration
|
||||
- Main config in `src/config/website.tsx`
|
||||
- Environment variables template in `env.example`
|
||||
- Database config in `drizzle.config.ts`
|
||||
- Biome config in `biome.json` with specific ignore patterns
|
||||
- TypeScript config with path aliases (@/* for src/*)
|
||||
|
||||
### Testing and Quality
|
||||
- Use Biome for linting and formatting
|
||||
- TypeScript for type safety
|
||||
- Environment variables for configuration
|
||||
- Proper error boundaries and not-found pages
|
||||
- Zod for runtime validation
|
||||
|
||||
## Important Notes
|
||||
|
||||
- The project uses pnpm as the package manager
|
||||
- Database schema is in `src/db/schema.ts` with auth, payment, and credit tables
|
||||
- Email templates are in `src/mail/templates/`
|
||||
- The app supports both light and dark themes
|
||||
- Content is managed through MDX files in the `content/` directory
|
||||
- The project includes comprehensive internationalization support
|
62
Dockerfile
Normal file
62
Dockerfile
Normal file
@ -0,0 +1,62 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies
|
||||
COPY package.json pnpm-lock.yaml* ./
|
||||
# Copy config files needed for fumadocs-mdx postinstall
|
||||
COPY source.config.ts ./
|
||||
COPY content ./content
|
||||
RUN npm install -g pnpm && pnpm i --frozen-lockfile
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Next.js collects completely anonymous telemetry data about general usage.
|
||||
# Learn more here: https://nextjs.org/telemetry
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN npm install -g pnpm \
|
||||
&& DOCKER_BUILD=true pnpm build
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
|
||||
# server.js is created by next build from the standalone output
|
||||
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
|
||||
CMD ["node", "server.js"]
|
41
LICENSE
Normal file
41
LICENSE
Normal file
@ -0,0 +1,41 @@
|
||||
MkSaaS License
|
||||
|
||||
Personal, Team, or Organization License
|
||||
|
||||
MkSaaS grants you an ongoing, non-exclusive license to use the software components and templates included in the SaaS Starter Kit.
|
||||
|
||||
The license permits usage by a single individual, team, or organization (the Licensee) and does not transfer to additional individuals, teams, or organizations without explicit permission.
|
||||
|
||||
You can:
|
||||
|
||||
- Use MkSaaS to create unlimited end products.
|
||||
- Modify MkSaaS components to create derivative works, subject to this license.
|
||||
- Use MkSaaS to create projects for unlimited clients.
|
||||
- Use MkSaaS to create end products sold to end users.
|
||||
- Use MkSaaS to build and run SaaS applications where end users interact with your end product.
|
||||
|
||||
You cannot:
|
||||
|
||||
- Redistribute MkSaaS’s components or templates, even if modified, separately from an end product.
|
||||
- Share your access to MkSaaS with anyone outside your team or organization without explicit permission.
|
||||
- Use MkSaaS to create products that compete with MkSaaS or provide a SaaS starter kit in conflict with MkSaaS’s business.
|
||||
|
||||
Example Usage
|
||||
|
||||
Examples of permitted usage:
|
||||
|
||||
- Creating personal, team, or organizational websites or applications.
|
||||
- Building commercial SaaS applications or web apps for clients.
|
||||
|
||||
Examples of prohibited usage:
|
||||
|
||||
- Creating a repository of MkSaaS (components) and sharing or selling it.
|
||||
- Making a derivative product (e.g. starter kit) and offering it for sale or free.
|
||||
|
||||
Enforcement and Liability
|
||||
|
||||
MkSaaS reserves the right to revoke licenses in case of a material breach of this agreement. The liability of MkSaaS is limited to the refund of the license fee. This agreement is governed by the laws of Switzerland.
|
||||
|
||||
Questions?
|
||||
|
||||
Unsure if your use case is covered by the license? Email us at support@MkSaaS.com with your questions.
|
56
README.md
56
README.md
@ -1,36 +1,46 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
# MkSaaS
|
||||
|
||||
## Getting Started
|
||||
Make AI SaaS in a weekend.
|
||||
|
||||
First, run the development server:
|
||||
The complete Next.js boilerplate for building profitable SaaS, with auth, payments, i18n, newsletter, dashboard, blog, docs, blocks, themes, SEO and more.
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
## Author
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
This project is created by [Fox](https://x.com/indie_maker_fox), the founder of [MkSaaS](https://mksaas.com) and [Mkdirs](https://mkdirs.com). The official X account for [MkSaaS](https://mksaas.com) is [@mksaascom](https://x.com/mksaascom), you can follow this account for the updates about MkSaaS.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
## Documentation
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
The documentation is available on the [website](https://mksaas.com/docs). It includes guides, tutorials, and detailed explanations of the code. I designed it to be as beginner-friendly as possible, so you can start making money from day one.
|
||||
|
||||
## Learn More
|
||||
If you found anything that could be improved, please let me know.
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
## Links
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
- 🔥 website: [mksaas.com](https://mksaas.com)
|
||||
- 🌐 demo: [demo.mksaas.com](https://demo.mksaas.com)
|
||||
- 📚 documentation: [mksaas.com/docs](https://mksaas.com/docs)
|
||||
- 🗓️ roadmap: [mksaas roadmap](https://mksaas.link/roadmap)
|
||||
- 👨💻 discord: [mksaas.link/discord](https://mksaas.link/discord)
|
||||
- 📹 video: [mksaas.link/youtube](https://mksaas.link/youtube)
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
## Repositories
|
||||
|
||||
## Deploy on Vercel
|
||||
By default, you should have access to all 5 repositories. If you find that you’re unable to access any of them, please don’t hesitate to reach out to me, and I’ll assist you in resolving the issue.
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
- [mksaas-template (ready)](https://github.com/MkSaaSHQ/mksaas-template): https://demo.mksaas.com
|
||||
- [mksaas-blog (ready)](https://github.com/MkSaaSHQ/mksaas-blog): https://mksaas.me
|
||||
- [mksaas-haitang (ready)](https://github.com/MkSaaSHQ/mksaas-haitang): https://haitang.app
|
||||
- [mksaas-outfit (ready)](https://github.com/MkSaaSHQ/mksaas-outfit)
|
||||
- [mksaas-app (WIP)](https://github.com/MkSaaSHQ/mksaas-app): https://mksaas.app
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
## Notice
|
||||
|
||||
> If you have any questions, please [submit an issue](https://github.com/MkSaaSHQ/mksaas-template/issues/new), or contact me at [support@mksaas.com](mailto:support@mksaas.com), or join our [discord community](https://mksaas.link/discord) and ask for help there.
|
||||
|
||||
> If you want to receive notifications whenever code changes, please click `Watch` button in the top right.
|
||||
|
||||
> When submitting any content to the issues of the repository, please use **English** as the main Language, so that everyone can read it and help you, thank you for your supports.
|
||||
|
||||
## License
|
||||
|
||||
For any details on the license, please refer to the [License](LICENSE) file.
|
||||
|
108
biome.json
Normal file
108
biome.json
Normal file
@ -0,0 +1,108 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"vcs": {
|
||||
"enabled": false,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": false
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": true,
|
||||
"ignore": [
|
||||
".next/**",
|
||||
".open-next/**",
|
||||
".wrangler/**",
|
||||
".cursor/**",
|
||||
".claude/**",
|
||||
".kiro/**",
|
||||
".conductor/**",
|
||||
".vscode/**",
|
||||
".source/**",
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
"build/**",
|
||||
"src/db/**",
|
||||
"tailwind.config.ts",
|
||||
"src/components/ui/*.tsx",
|
||||
"src/components/magicui/*.tsx",
|
||||
"src/components/animate-ui/*.tsx",
|
||||
"src/components/tailark/*.tsx",
|
||||
"src/components/ai-elements/*.tsx",
|
||||
"src/app/[[]locale]/preview/**",
|
||||
"src/payment/types.ts",
|
||||
"src/credits/types.ts",
|
||||
"src/types/index.d.ts"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 80,
|
||||
"formatWithErrors": true,
|
||||
"useEditorconfig": true
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"suspicious": {
|
||||
"noSparseArray": "off",
|
||||
"noArrayIndexKey": "off",
|
||||
"noExplicitAny": "off",
|
||||
"noShadowRestrictedNames": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noForEach": "off"
|
||||
},
|
||||
"correctness": {
|
||||
"useExhaustiveDependencies": "off"
|
||||
},
|
||||
"style": {
|
||||
"useTemplate": "off",
|
||||
"noNonNullAssertion": "off",
|
||||
"useShorthandArrayType": "off",
|
||||
"useNodejsImportProtocol": "off"
|
||||
},
|
||||
"a11y": {
|
||||
"useValidAnchor": "off",
|
||||
"noSvgWithoutTitle": "off",
|
||||
"useKeyWithClickEvents": "off"
|
||||
}
|
||||
},
|
||||
"ignore": [
|
||||
".next/**",
|
||||
".open-next/**",
|
||||
".wrangler/**",
|
||||
".cursor/**",
|
||||
".claude/**",
|
||||
".conductor/**",
|
||||
".kiro/**",
|
||||
".vscode/**",
|
||||
".source/**",
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
"build/**",
|
||||
"src/db/**",
|
||||
"tailwind.config.ts",
|
||||
"src/components/ui/*.tsx",
|
||||
"src/components/magicui/*.tsx",
|
||||
"src/components/animate-ui/*.tsx",
|
||||
"src/components/tailark/*.tsx",
|
||||
"src/components/ai-elements/*.tsx",
|
||||
"src/app/[[]locale]/preview/**",
|
||||
"src/payment/types.ts",
|
||||
"src/credits/types.ts",
|
||||
"src/types/index.d.ts"
|
||||
]
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "single",
|
||||
"trailingCommas": "es5",
|
||||
"semicolons": "always"
|
||||
}
|
||||
}
|
||||
}
|
7483
cloudflare-env.d.ts
vendored
Normal file
7483
cloudflare-env.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"style": "new-york",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src/app/globals.css",
|
||||
"config": "",
|
||||
"css": "src/styles/globals.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
@ -18,4 +18,4 @@
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
}
|
||||
|
4
content/author/fox.mdx
Normal file
4
content/author/fox.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Fox
|
||||
avatar: /images/avatars/fox.png
|
||||
---
|
4
content/author/fox.zh.mdx
Normal file
4
content/author/fox.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Fox
|
||||
avatar: /images/avatars/fox.png
|
||||
---
|
4
content/author/mkdirs.mdx
Normal file
4
content/author/mkdirs.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Mkdirs
|
||||
avatar: /images/avatars/mkdirs.png
|
||||
---
|
4
content/author/mkdirs.zh.mdx
Normal file
4
content/author/mkdirs.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Mkdirs模板
|
||||
avatar: /images/avatars/mkdirs.png
|
||||
---
|
4
content/author/mksaas.mdx
Normal file
4
content/author/mksaas.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: MkSaaS
|
||||
avatar: /images/avatars/mksaas.png
|
||||
---
|
4
content/author/mksaas.zh.mdx
Normal file
4
content/author/mksaas.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: MkSaaS模板
|
||||
avatar: /images/avatars/mksaas.png
|
||||
---
|
78
content/blog/comparisons.mdx
Normal file
78
content/blog/comparisons.mdx
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
title: Comparisons
|
||||
description: How is Fumadocs different from other existing frameworks?
|
||||
image: /images/blog/post-2.png
|
||||
date: "2025-03-22"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
---
|
||||
|
||||
## Nextra
|
||||
|
||||
Fumadocs is highly inspired by Nextra. For example, the Routing Conventions. That is why
|
||||
`meta.json` also exists in Fumadocs.
|
||||
|
||||
Nextra is more opinionated than Fumadocs. Fumadocs is accelerated by App Router. As a result, It provides many server-side functions, and you have to
|
||||
configure things manually compared to simply editing a configuration file.
|
||||
|
||||
Fumadocs works great if you want more control over everything, such as
|
||||
adding it to an existing codebase or implementing advanced routing.
|
||||
|
||||
### Feature Table
|
||||
|
||||
| Feature | Fumadocs | Nextra |
|
||||
| ------------------- | ------------ | ------------------------- |
|
||||
| Static Generation | Yes | Yes |
|
||||
| Cached | Yes | Yes |
|
||||
| Light/Dark Mode | Yes | Yes |
|
||||
| Syntax Highlighting | Yes | Yes |
|
||||
| Table of Contents | Yes | Yes |
|
||||
| Full-text Search | Yes | Yes |
|
||||
| i18n | Yes | Yes |
|
||||
| Last Git Edit Time | Yes | Yes |
|
||||
| Page Icons | Yes | Yes, via `_meta.js` files |
|
||||
| RSC | Yes | Yes |
|
||||
| Remote Source | Yes | Yes |
|
||||
| SEO | Via Metadata | Yes |
|
||||
| Built-in Components | Yes | Yes |
|
||||
| RTL Layout | Yes | Yes |
|
||||
|
||||
### Additional Features
|
||||
|
||||
Features supported via 3rd party libraries like [TypeDoc](https://typedoc.org) will not be listed here.
|
||||
|
||||
| Feature | Fumadocs | Nextra |
|
||||
| -------------------------- | -------- | ------ |
|
||||
| OpenAPI Integration | Yes | No |
|
||||
| TypeScript Docs Generation | Yes | No |
|
||||
| TypeScript Twoslash | Yes | Yes |
|
||||
|
||||
## Mintlify
|
||||
|
||||
Mintlify is a documentation service, as compared to Fumadocs, it offers a free tier but isn't completely free and open source.
|
||||
|
||||
Fumadocs is not as powerful as Mintlify, for example, the OpenAPI integration of Mintlify.
|
||||
As the creator of Fumadocs, I wouldn't recommend switching to Fumadocs from Mintlify if you're satisfied with the current way you build docs.
|
||||
However, I believe Fumadocs is a suitable tool for all Next.js developers who want to have elegant docs.
|
||||
|
||||
## Docusaurus
|
||||
|
||||
Docusaurus is a powerful framework based on React.js. It offers many cool
|
||||
features with plugins and custom themes.
|
||||
|
||||
### Better DX
|
||||
|
||||
Since Fumadocs is built on the top of Next.js, you'll have to start the Next.js dev
|
||||
server every time to review changes, and initial boilerplate code is relatively more
|
||||
compared to Docusaurus.
|
||||
|
||||
For a simple docs, Docusaurus might be a better choice if you don't need any Next.js specific functionality.
|
||||
|
||||
However, when you want to use Next.js, or seek extra customizability like tuning default UI components, Fumadocs could be a better choice.
|
||||
|
||||
### Plugins
|
||||
|
||||
You can easily achieve many things with plugins, their ecosystem is indeed larger and maintained by many contributors.
|
||||
|
||||
In comparison, the flexibility of Fumadocs allows you to implement them on your own, it may take longer to tune it to your satisfaction.
|
72
content/blog/comparisons.zh.mdx
Normal file
72
content/blog/comparisons.zh.mdx
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: 对比
|
||||
description: Fumadocs 与其他现有框架有何不同?
|
||||
image: /images/blog/post-2.png
|
||||
date: "2025-03-22"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
---
|
||||
|
||||
## Nextra
|
||||
|
||||
Fumadocs 深受 Nextra 启发。例如,路由约定。这就是为什么 Fumadocs 中也存在 `meta.json`。
|
||||
|
||||
Nextra 比 Fumadocs 更加固执己见。Fumadocs 由 App Router 加速。因此,它提供了许多服务器端功能,与简单编辑配置文件相比,您必须手动配置一些内容。
|
||||
|
||||
如果您想要对一切都有更多的控制,比如将其添加到现有代码库或实现高级路由,Fumadocs 会表现得很出色。
|
||||
|
||||
### 功能表
|
||||
|
||||
| 功能 | Fumadocs | Nextra |
|
||||
| ------------------- | ------------ | ------------------------- |
|
||||
| 静态生成 | 是 | 是 |
|
||||
| 缓存 | 是 | 是 |
|
||||
| 明/暗模式 | 是 | 是 |
|
||||
| 语法高亮 | 是 | 是 |
|
||||
| 目录 | 是 | 是 |
|
||||
| 全文搜索 | 是 | 是 |
|
||||
| 国际化 | 是 | 是 |
|
||||
| 最后 Git 编辑时间 | 是 | 是 |
|
||||
| 页面图标 | 是 | 是,通过 `_meta.js` 文件 |
|
||||
| RSC | 是 | 是 |
|
||||
| 远程源 | 是 | 是 |
|
||||
| SEO | 通过元数据 | 是 |
|
||||
| 内置组件 | 是 | 是 |
|
||||
| RTL 布局 | 是 | 是 |
|
||||
|
||||
### 附加功能
|
||||
|
||||
通过第三方库支持的功能(如 [TypeDoc](https://typedoc.org))不会在此列出。
|
||||
|
||||
| 功能 | Fumadocs | Nextra |
|
||||
| -------------------------- | -------- | ------ |
|
||||
| OpenAPI 集成 | 是 | 否 |
|
||||
| TypeScript 文档生成 | 是 | 否 |
|
||||
| TypeScript Twoslash | 是 | 是 |
|
||||
|
||||
## Mintlify
|
||||
|
||||
Mintlify 是一项文档服务,与 Fumadocs 相比,它提供免费套餐,但并非完全免费和开源。
|
||||
|
||||
Fumadocs 不如 Mintlify 强大,例如 Mintlify 的 OpenAPI 集成。
|
||||
作为 Fumadocs 的创建者,如果您对当前构建文档的方式感到满意,我不建议从 Mintlify 切换到 Fumadocs。
|
||||
然而,我相信 Fumadocs 是所有想要拥有优雅文档的 Next.js 开发者的合适工具。
|
||||
|
||||
## Docusaurus
|
||||
|
||||
Docusaurus 是一个基于 React.js 的强大框架。它通过插件和自定义主题提供了许多酷炫的功能。
|
||||
|
||||
### 更好的开发者体验
|
||||
|
||||
由于 Fumadocs 构建在 Next.js 之上,您每次都必须启动 Next.js 开发服务器来查看更改,并且相对于 Docusaurus,初始样板代码较多。
|
||||
|
||||
对于简单的文档,如果您不需要任何特定于 Next.js 的功能,Docusaurus 可能是更好的选择。
|
||||
|
||||
然而,当您想要使用 Next.js,或寻求更多的可定制性,如调整默认 UI 组件时,Fumadocs 可能是更好的选择。
|
||||
|
||||
### 插件
|
||||
|
||||
您可以通过插件轻松实现许多功能,他们的生态系统确实更大,并由许多贡献者维护。
|
||||
|
||||
相比之下,Fumadocs 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。
|
278
content/blog/fumadocs.mdx
Normal file
278
content/blog/fumadocs.mdx
Normal file
@ -0,0 +1,278 @@
|
||||
---
|
||||
title: Quick Start
|
||||
description: Getting Started with Fumadocs
|
||||
image: /images/blog/post-8.png
|
||||
date: "2025-03-28"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> is a **documentation framework** based on Next.js, designed to be fast, flexible,
|
||||
and composes seamlessly into Next.js App Router.
|
||||
|
||||
Fumadocs has different parts:
|
||||
|
||||
<Cards>
|
||||
|
||||
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
|
||||
|
||||
Handles most of the logic, including document search, content source adapters, and Markdown extensions.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
|
||||
|
||||
The default theme of Fumadocs offers a beautiful look for documentation sites and interactive components.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Database />} title='Content Source'>
|
||||
|
||||
The source of your content, can be a CMS or local data layers like [Content Collections](https://www.content-collections.dev) and [Fumadocs MDX](/docs/mdx), the official content source.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Terminal />} title='Fumadocs CLI'>
|
||||
|
||||
A command line tool to install UI components and automate things, useful for customizing layouts.
|
||||
|
||||
</Card>
|
||||
|
||||
</Cards>
|
||||
|
||||
<Callout title="Want to learn more?">
|
||||
Read our in-depth [What is Fumadocs](/docs/what-is-fumadocs) introduction.
|
||||
</Callout>
|
||||
|
||||
### Terminology
|
||||
|
||||
**Markdown/MDX:** Markdown is a markup language for creating formatted text. Fumadocs supports Markdown and MDX (superset of Markdown) out-of-the-box.
|
||||
|
||||
Although not required, some basic knowledge of Next.js App Router would be useful for further customisations.
|
||||
|
||||
## Automatic Installation
|
||||
|
||||
A minimum version of Node.js 18 required, note that Node.js 23.1 might have problems with Next.js production build.
|
||||
|
||||
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
|
||||
|
||||
```bash tab="npm"
|
||||
npm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="pnpm"
|
||||
pnpm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="yarn"
|
||||
yarn create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="bun"
|
||||
bun create fumadocs-app
|
||||
```
|
||||
|
||||
</Tabs>
|
||||
|
||||
It will ask you the framework and content source to use, a new fumadocs app should be initialized. Now you can start hacking!
|
||||
|
||||
<Callout title='From Existing Codebase?'>
|
||||
|
||||
You can follow the [Manual Installation](/docs/manual-installation) guide to get started.
|
||||
|
||||
</Callout>
|
||||
|
||||
### Enjoy!
|
||||
|
||||
Create your first MDX file in the docs folder.
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Yo what's up
|
||||
```
|
||||
|
||||
Run the app in development mode and see http://localhost:3000/docs.
|
||||
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Explore
|
||||
|
||||
In the project, you can see:
|
||||
|
||||
- `lib/source.ts`: Code for content source adapter, [`loader()`](/docs/headless/source-api) provides an interface to interact with your content source, and assigns URL to your pages.
|
||||
- `app/layout.config.tsx`: Shared options for layouts, optional but preferred to keep.
|
||||
|
||||
| Route | Description |
|
||||
| ------------------------- | ------------------------------------------------------ |
|
||||
| `app/(home)` | The route group for your landing page and other pages. |
|
||||
| `app/docs` | The documentation layout and pages. |
|
||||
| `app/api/search/route.ts` | The Route Handler for search. |
|
||||
|
||||
### Writing Content
|
||||
|
||||
For authoring docs, make sure to read:
|
||||
|
||||
<Cards>
|
||||
<Card href="/docs/markdown" title="Markdown">
|
||||
Fumadocs has some additional features for authoring content too.
|
||||
</Card>
|
||||
<Card href="/docs/navigation" title="Navigation">
|
||||
Learn how to customise navigation links/sidebar items.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Content Source
|
||||
|
||||
Content source handles all your content, like compiling Markdown files and validating frontmatter.
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
|
||||
Read the [Introduction](/docs/mdx) to learn how it handles your content.
|
||||
|
||||
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Custom Source'>
|
||||
|
||||
Fumadocs is not Markdown-exclusive. For other sources like Sanity, you can build a [custom content source](/docs/headless/custom-source).
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### Customise UI
|
||||
|
||||
See [Customisation Guide](/docs/customisation).
|
||||
|
||||
## FAQ
|
||||
|
||||
Some common questions you may encounter.
|
||||
|
||||
<Accordions>
|
||||
<Accordion id='fix-monorepo-styling' title="How to fix stylings not being applied in Monorepo?">
|
||||
|
||||
Sometimes, `fumadocs-ui` is not installed in the workspace of your Tailwind CSS configuration file. (e.g. a monorepo setup).
|
||||
|
||||
You have to ensure the `fumadocs-ui` package is scanned by Tailwind CSS, and give a correct relative path to `@source`.
|
||||
|
||||
For example, add `../../` to point to the `node_modules` folder in root workspace.
|
||||
|
||||
```css
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* [!code --] */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
/* [!code ++] */
|
||||
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='change-base-url' title="How to change the base route of /docs?">
|
||||
|
||||
You can change the base route of docs (e.g. from `/docs/page` to `/info/page`).
|
||||
Since Fumadocs uses Next.js App Router, you can simply rename the route:
|
||||
|
||||
<Files>
|
||||
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
<Folder name="app/info" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
And tell Fumadocs to use the new route in `source.ts`:
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: '/info',
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='dynamic-route' title="It uses Dynamic Route, will it be poor in performance?">
|
||||
|
||||
Next.js turns dynamic route into static routes when `generateStaticParams` is configured.
|
||||
Hence, it is as fast as static pages.
|
||||
|
||||
You can enable Static Exports on Next.js to get a static build output. (Notice that Route Handler doesn't work with static export, you have to configure static search)
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='custom-layout-docs-page' title='How to create a page in /docs without docs layout?'>
|
||||
|
||||
Same as managing layouts in Next.js App Router, remove the original MDX file from content directory (`/content/docs`).
|
||||
This ensures duplicated pages will not cause errors.
|
||||
|
||||
Now, You can add the page to another route group, which isn't a descendant of docs layout.
|
||||
|
||||
For example, under your `app` folder:
|
||||
|
||||
<Files>
|
||||
<File name="(home)/docs/page.tsx" />
|
||||
<Folder name="docs">
|
||||
<File name="layout.tsx" />
|
||||
<File name="[[...slug]]/page.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
will replace the `/docs` page with your `page.tsx`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-versions' title="How to implement docs with multi-version?">
|
||||
Use a separate deployment for each version.
|
||||
|
||||
On Vercel, this can be done by creating another branch for a specific version on your GitHub repository.
|
||||
To link to the sites of other versions, use the Links API or a custom navigation component.
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-docs' title="How to implement multi-docs?">
|
||||
We recommend to use [Sidebar Tabs](/docs/navigation/sidebar#sidebar-tabs).
|
||||
</Accordion>
|
||||
|
||||
</Accordions>
|
||||
|
||||
## Learn More
|
||||
|
||||
New to here? Don't worry, we are welcome for your questions.
|
||||
|
||||
If you find anything confusing, please give your feedback on [Github Discussion](https://github.com/fuma-nama/fumadocs/discussions)!
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="/docs/static-export"
|
||||
title="Configure Static Export"
|
||||
description="Learn how to enable static export on your docs"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/search"
|
||||
title="Customise Search"
|
||||
description="Learn how to customise document search"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/theme"
|
||||
title="Theming"
|
||||
description="Add themes to Fumadocs UI"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/components"
|
||||
title="Components"
|
||||
description="See all available components to enhance your docs"
|
||||
/>
|
||||
</Cards>
|
253
content/blog/fumadocs.zh.mdx
Normal file
253
content/blog/fumadocs.zh.mdx
Normal file
@ -0,0 +1,253 @@
|
||||
---
|
||||
title: 快速入门
|
||||
description: Fumadocs 入门指南
|
||||
image: /images/blog/post-8.png
|
||||
date: "2025-03-28"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
## 简介
|
||||
|
||||
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> 是一个基于 Next.js 的**文档框架**,设计为快速、灵活,
|
||||
并无缝集成到 Next.js App Router 中。
|
||||
|
||||
Fumadocs 由不同部分组成:
|
||||
|
||||
<Cards>
|
||||
|
||||
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
|
||||
|
||||
处理大部分逻辑,包括文档搜索、内容源适配器和 Markdown 扩展。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
|
||||
|
||||
Fumadocs 的默认主题为文档站点提供了美观的外观和交互式组件。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Database />} title='Content Source'>
|
||||
|
||||
您内容的来源,可以是 CMS 或本地数据层,如 [Content Collections](https://www.content-collections.dev) 和 [Fumadocs MDX](/docs/mdx),即官方内容源。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Terminal />} title='Fumadocs CLI'>
|
||||
|
||||
一个命令行工具,用于安装 UI 组件和自动化操作,对于自定义布局非常有用。
|
||||
|
||||
</Card>
|
||||
|
||||
</Cards>
|
||||
|
||||
<Callout title="想了解更多?">
|
||||
阅读我们深入的 [什么是 Fumadocs](/docs/what-is-fumadocs) 介绍。
|
||||
</Callout>
|
||||
|
||||
### 术语
|
||||
|
||||
**Markdown/MDX:** Markdown 是一种用于创建格式化文本的标记语言。Fumadocs 默认支持 Markdown 和 MDX(Markdown 的超集)。
|
||||
|
||||
虽然不是必需的,但对 Next.js App Router 的基本了解对于进一步的自定义会很有帮助。
|
||||
|
||||
## 自动安装
|
||||
|
||||
需要 Node.js 18 或更高版本,请注意 Node.js 23.1 可能在 Next.js 生产构建中存在问题。
|
||||
|
||||
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
|
||||
|
||||
```bash tab="npm"
|
||||
npm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="pnpm"
|
||||
pnpm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="yarn"
|
||||
yarn create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="bun"
|
||||
bun create fumadocs-app
|
||||
```
|
||||
|
||||
</Tabs>
|
||||
|
||||
它会询问您要使用的框架和内容源,随后将初始化一个新的 fumadocs 应用程序。现在您可以开始动手了!
|
||||
|
||||
<Callout title='从现有代码库开始?'>
|
||||
|
||||
您可以按照 [手动安装](/docs/manual-installation) 指南开始。
|
||||
|
||||
</Callout>
|
||||
|
||||
### 尽情使用!
|
||||
|
||||
在 docs 文件夹中创建您的第一个 MDX 文件。
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Yo what's up
|
||||
```
|
||||
|
||||
在开发模式下运行应用程序并查看 http://localhost:3000/docs。
|
||||
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 探索
|
||||
|
||||
在项目中,您可以看到:
|
||||
|
||||
- `lib/source.ts`:内容源适配器的代码,[`loader()`](/docs/headless/source-api) 提供了与内容源交互的接口,并为您的页面分配 URL。
|
||||
- `app/layout.config.tsx`:布局的共享选项,可选但建议保留。
|
||||
|
||||
| 路由 | 描述 |
|
||||
| ------------------------- | -------------------------------------- |
|
||||
| `app/(home)` | 您的登陆页面和其他页面的路由组。 |
|
||||
| `app/docs` | 文档布局和页面。 |
|
||||
| `app/api/search/route.ts` | 搜索的路由处理器。 |
|
||||
|
||||
### 编写内容
|
||||
|
||||
对于编写文档,请务必阅读:
|
||||
|
||||
<Cards>
|
||||
<Card href="/docs/markdown" title="Markdown">
|
||||
Fumadocs 还有一些额外的内容创作功能。
|
||||
</Card>
|
||||
<Card href="/docs/navigation" title="Navigation">
|
||||
了解如何自定义导航链接/侧边栏项目。
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### 内容源
|
||||
|
||||
内容源处理您的所有内容,例如编译 Markdown 文件和验证前言。
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
|
||||
阅读 [介绍](/docs/mdx) 了解它如何处理您的内容。
|
||||
|
||||
项目中已包含 `source.config.ts` 配置文件,您可以自定义不同的选项,如前言模式。
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Custom Source'>
|
||||
|
||||
Fumadocs 不仅限于 Markdown。对于其他源(如 Sanity),您可以构建 [自定义内容源](/docs/headless/custom-source)。
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### 自定义 UI
|
||||
|
||||
请参阅 [自定义指南](/docs/customisation)。
|
||||
|
||||
## 常见问题
|
||||
|
||||
您可能遇到的一些常见问题。
|
||||
|
||||
<Accordions>
|
||||
<Accordion id='fix-monorepo-styling' title="如何修复 Monorepo 中样式不应用的问题?">
|
||||
|
||||
有时,`fumadocs-ui` 没有安装在您的 Tailwind CSS 配置文件的工作区中(例如,在 monorepo 设置中)。
|
||||
|
||||
您必须确保 Tailwind CSS 扫描 `fumadocs-ui` 包,并为 `@source` 提供正确的相对路径。
|
||||
|
||||
例如,添加 `../../` 指向根工作区中的 `node_modules` 文件夹。
|
||||
|
||||
```css
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* [!code --] */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
/* [!code ++] */
|
||||
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='change-base-url' title="如何更改 /docs 的基本路由?">
|
||||
|
||||
您可以更改文档的基本路由(例如,从 `/docs/page` 更改为 `/info/page`)。
|
||||
由于 Fumadocs 使用 Next.js App Router,您可以简单地重命名路由:
|
||||
|
||||
<Files>
|
||||
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
<Folder name="app/info" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
并在 `source.ts` 中告诉 Fumadocs 使用新的路由:
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: '/info',
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='dynamic-route' title="它使用动态路由,性能会很差吗?">
|
||||
|
||||
当配置了 `generateStaticParams` 时,Next.js 会将动态路由转换为静态路由。
|
||||
因此,它与静态页面一样快。
|
||||
|
||||
您可以在 Next.js 上启用静态导出,获得静态构建输出。(请注意,路由处理器不适用于静态导出,您必须配置静态搜索)
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='custom-layout-docs-page' title='如何在 /docs 中创建没有文档布局的页面?'>
|
||||
|
||||
与在 Next.js App Router 中管理布局相同,从内容目录(`/content/docs`)中删除原始 MDX 文件。
|
||||
这确保重复的页面不会导致错误。
|
||||
|
||||
现在,您可以将页面添加到另一个路由组,该组不是文档布局的后代。
|
||||
|
||||
例如,在您的 `app` 文件夹下:
|
||||
|
||||
<Files>
|
||||
<File name="(home)/docs/page.tsx" />
|
||||
<Folder name="docs">
|
||||
<File name="layout.tsx" />
|
||||
<File name="[[...slug]]/page.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
将用您的 `page.tsx` 替换 `/docs` 页面。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-versions' title="如何实现多版本文档?">
|
||||
为每个版本使用单独的部署。
|
||||
|
||||
在 Vercel 上,可以通过在 GitHub 存储库中为特定版本创建另一个分支来实现。
|
||||
要链接到其他版本的站点,请使用 Links API 或自定义导航组件。
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-docs' title="如何实现多文档?">
|
||||
我们建议使用 [侧边栏标签](/docs/navigation/sidebar#sidebar-tabs)。
|
||||
</Accordion>
|
||||
|
||||
</Accordions>
|
||||
|
||||
## 了解更多
|
||||
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
227
content/blog/internationalization.mdx
Normal file
227
content/blog/internationalization.mdx
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
title: Internationalization
|
||||
description: Support multiple languages in your documentation
|
||||
image: /images/blog/post-3.png
|
||||
date: "2025-03-15"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
<Callout title='Before you get started'>
|
||||
|
||||
Fumadocs is not a full-powered i18n library, it manages only its own components and utilities.
|
||||
|
||||
You can use other libraries like [next-intl](https://github.com/amannn/next-intl) for the rest of your app.
|
||||
Read the [Next.js Docs](https://nextjs.org/docs/app/building-your-application/routing/internationalization) to learn more about implementing I18n in Next.js.
|
||||
|
||||
</Callout>
|
||||
|
||||
## Manual Setup
|
||||
|
||||
Define the i18n configurations in a file, we will import it with `@/ilb/i18n` in this guide.
|
||||
|
||||
{/* <include cwd meta='title="lib/i18n.ts"'>
|
||||
../../examples/i18n/lib/i18n.ts
|
||||
</include> */}
|
||||
|
||||
Pass it to the source loader.
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
i18n, // [!code highlight]
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
And update Fumadocs UI layout options.
|
||||
|
||||
```tsx title="app/layout.config.tsx"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
|
||||
|
||||
export function baseOptions(locale: string): BaseLayoutProps {
|
||||
return {
|
||||
i18n,
|
||||
// different props based on `locale`
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Middleware
|
||||
|
||||
Create a middleware that redirects users to appropriate locale.
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/i18n/middleware.ts",
|
||||
"codeblock": {
|
||||
"lang": "ts",
|
||||
"meta": "title=\"middleware.ts\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See [Middleware](/docs/headless/internationalization#middleware) for customisable options.
|
||||
|
||||
> Note that this is optional, you can also use your own middleware or the one provided by i18n libraries.
|
||||
|
||||
### Routing
|
||||
|
||||
Create a `/app/[lang]` folder, and move all files (e.g. `page.tsx`, `layout.tsx`) from `/app` to the folder.
|
||||
|
||||
Wrap the root provider inside `I18nProvider`, and provide available languages & translations to it.
|
||||
Note that only English translations are provided by default.
|
||||
|
||||
```tsx title="app/[lang]/layout.tsx"
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
|
||||
|
||||
const cn: Partial<Translations> = {
|
||||
search: 'Translated Content',
|
||||
// other translations
|
||||
};
|
||||
|
||||
// available languages that will be displayed on UI
|
||||
// make sure `locale` is consistent with your i18n config
|
||||
const locales = [
|
||||
{
|
||||
name: 'English',
|
||||
locale: 'en',
|
||||
},
|
||||
{
|
||||
name: 'Chinese',
|
||||
locale: 'cn',
|
||||
},
|
||||
];
|
||||
|
||||
export default async function RootLayout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const lang = (await params).lang;
|
||||
|
||||
return (
|
||||
<html lang={lang}>
|
||||
<body>
|
||||
<I18nProvider
|
||||
locale={lang}
|
||||
locales={locales}
|
||||
translations={{ cn }[lang]}
|
||||
>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</I18nProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Pass Locale
|
||||
|
||||
Pass the locale to Fumadocs in your pages and layouts.
|
||||
|
||||
{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return (
|
||||
<DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```ts title="page.tsx" tab="Docs Page"
|
||||
import { source } from '@/lib/source';
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ lang: string; slug?: string[] }>;
|
||||
}) {
|
||||
const { slug, lang } = await params;
|
||||
// get page
|
||||
source.getPage(slug); // [!code --]
|
||||
source.getPage(slug, lang); // [!code ++]
|
||||
|
||||
// get pages
|
||||
source.getPages(); // [!code --]
|
||||
source.getPages(lang); // [!code ++]
|
||||
}
|
||||
``` */}
|
||||
|
||||
### Search
|
||||
|
||||
Configure i18n on your search solution.
|
||||
|
||||
- **Built-in Search (Orama):**
|
||||
For [Supported Languages](https://docs.orama.com/open-source/supported-languages#officially-supported-languages), no further changes are needed.
|
||||
|
||||
Otherwise, additional config is required (e.g. Chinese & Japanese). See [Special Languages](/docs/headless/search/orama#special-languages).
|
||||
|
||||
- **Cloud Solutions (e.g. Algolia):**
|
||||
They usually have official support for multilingual.
|
||||
|
||||
## Writing Documents
|
||||
|
||||
{/* <include>../../shared/page-conventions.i18n.mdx</include> */}
|
||||
|
||||
## Navigation
|
||||
|
||||
Fumadocs only handles navigation for its own layouts (e.g. sidebar).
|
||||
For other places, you can use the `useParams` hook to get the locale from url, and attend it to `href`.
|
||||
|
||||
```tsx
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
|
||||
const { lang } = useParams();
|
||||
|
||||
return <Link href={`/${lang}/another-page`}>This is a link</Link>;
|
||||
```
|
||||
|
||||
In addition, the [`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) component supports dynamic hrefs, you can use it to attend the locale prefix.
|
||||
It is useful for Markdown/MDX content.
|
||||
|
||||
```mdx title="content.mdx"
|
||||
import { DynamicLink } from 'fumadocs-core/dynamic-link';
|
||||
|
||||
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
|
||||
```
|
227
content/blog/internationalization.zh.mdx
Normal file
227
content/blog/internationalization.zh.mdx
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
title: 国际化
|
||||
description: 在您的文档中支持多种语言
|
||||
image: /images/blog/post-3.png
|
||||
date: "2025-03-15"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
<Callout title='开始之前'>
|
||||
|
||||
Fumadocs 不是一个功能齐全的 i18n 库,它只管理自己的组件和工具。
|
||||
|
||||
您可以使用其他库,如 [next-intl](https://github.com/amannn/next-intl),用于应用程序的其余部分。
|
||||
阅读 [Next.js 文档](https://nextjs.org/docs/app/building-your-application/routing/internationalization),了解更多关于在 Next.js 中实现 I18n 的信息。
|
||||
|
||||
</Callout>
|
||||
|
||||
## 手动设置
|
||||
|
||||
在一个文件中定义 i18n 配置,我们将在本指南中使用 `@/ilb/i18n` 导入它。
|
||||
|
||||
{/* <include cwd meta='title="lib/i18n.ts"'>
|
||||
../../examples/i18n/lib/i18n.ts
|
||||
</include> */}
|
||||
|
||||
将其传递给源加载器。
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
i18n, // [!code highlight]
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
并更新 Fumadocs UI 布局选项。
|
||||
|
||||
```tsx title="app/layout.config.tsx"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
|
||||
|
||||
export function baseOptions(locale: string): BaseLayoutProps {
|
||||
return {
|
||||
i18n,
|
||||
// different props based on `locale`
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 中间件
|
||||
|
||||
创建一个将用户重定向到适当语言环境的中间件。
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/i18n/middleware.ts",
|
||||
"codeblock": {
|
||||
"lang": "ts",
|
||||
"meta": "title=\"middleware.ts\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
查看[中间件](/docs/headless/internationalization#middleware)了解可自定义选项。
|
||||
|
||||
> 请注意,这是可选的,您也可以使用自己的中间件或 i18n 库提供的中间件。
|
||||
|
||||
### 路由
|
||||
|
||||
创建一个 `/app/[lang]` 文件夹,并将所有文件(例如 `page.tsx`、`layout.tsx`)从 `/app` 移动到该文件夹。
|
||||
|
||||
将根提供程序包装在 `I18nProvider` 中,并向其提供可用语言和翻译。
|
||||
请注意,默认情况下只提供英文翻译。
|
||||
|
||||
```tsx title="app/[lang]/layout.tsx"
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
|
||||
|
||||
const cn: Partial<Translations> = {
|
||||
search: 'Translated Content',
|
||||
// other translations
|
||||
};
|
||||
|
||||
// available languages that will be displayed on UI
|
||||
// make sure `locale` is consistent with your i18n config
|
||||
const locales = [
|
||||
{
|
||||
name: 'English',
|
||||
locale: 'en',
|
||||
},
|
||||
{
|
||||
name: 'Chinese',
|
||||
locale: 'cn',
|
||||
},
|
||||
];
|
||||
|
||||
export default async function RootLayout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const lang = (await params).lang;
|
||||
|
||||
return (
|
||||
<html lang={lang}>
|
||||
<body>
|
||||
<I18nProvider
|
||||
locale={lang}
|
||||
locales={locales}
|
||||
translations={{ cn }[lang]}
|
||||
>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</I18nProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 传递区域设置
|
||||
|
||||
在您的页面和布局中将区域设置传递给 Fumadocs。
|
||||
|
||||
{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return (
|
||||
<DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```ts title="page.tsx" tab="Docs Page"
|
||||
import { source } from '@/lib/source';
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ lang: string; slug?: string[] }>;
|
||||
}) {
|
||||
const { slug, lang } = await params;
|
||||
// get page
|
||||
source.getPage(slug); // [!code --]
|
||||
source.getPage(slug, lang); // [!code ++]
|
||||
|
||||
// get pages
|
||||
source.getPages(); // [!code --]
|
||||
source.getPages(lang); // [!code ++]
|
||||
}
|
||||
``` */}
|
||||
|
||||
### 搜索
|
||||
|
||||
在您的搜索解决方案上配置 i18n。
|
||||
|
||||
- **内置搜索 (Orama):**
|
||||
对于[支持的语言](https://docs.orama.com/open-source/supported-languages#officially-supported-languages),无需进一步更改。
|
||||
|
||||
否则,需要额外配置(例如中文和日语)。请参阅[特殊语言](/docs/headless/search/orama#special-languages)。
|
||||
|
||||
- **云解决方案(例如 Algolia):**
|
||||
它们通常官方支持多语言。
|
||||
|
||||
## 编写文档
|
||||
|
||||
{/* <include>../../shared/page-conventions.i18n.mdx</include> */}
|
||||
|
||||
## 导航
|
||||
|
||||
Fumadocs 只处理其自己的布局(例如侧边栏)的导航。
|
||||
对于其他地方,您可以使用 `useParams` 钩子从 url 获取区域设置,并将其添加到 `href`。
|
||||
|
||||
```tsx
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
|
||||
const { lang } = useParams();
|
||||
|
||||
return <Link href={`/${lang}/another-page`}>This is a link</Link>;
|
||||
```
|
||||
|
||||
另外,[`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) 组件支持动态 hrefs,您可以使用它来添加区域设置前缀。
|
||||
这对于 Markdown/MDX 内容很有用。
|
||||
|
||||
```mdx title="content.mdx"
|
||||
import { DynamicLink } from 'fumadocs-core/dynamic-link';
|
||||
|
||||
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
|
||||
```
|
198
content/blog/manual-installation.mdx
Normal file
198
content/blog/manual-installation.mdx
Normal file
@ -0,0 +1,198 @@
|
||||
---
|
||||
title: Manual Installation
|
||||
description: Create a new fumadocs project from scratch.
|
||||
image: /images/blog/post-4.png
|
||||
date: "2025-03-14"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
> Read the [Quick Start](/docs) guide first for basic concept.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Create a new Next.js application with `create-next-app`, and install required packages.
|
||||
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
### Content Source
|
||||
|
||||
Fumadocs supports different content sources, you can choose one you prefer.
|
||||
|
||||
There is a list of officially supported sources:
|
||||
|
||||
- [Setup Fumadocs MDX](/docs/mdx)
|
||||
- [Setup Content Collections](/docs/headless/content-collections)
|
||||
|
||||
Make sure to configure the library correctly following their setup guide before continuing, we will import the source adapter using `@/lib/source.ts` in this guide.
|
||||
|
||||
### Root Layout
|
||||
|
||||
Wrap the entire application inside [Root Provider](/docs/layouts/root-provider), and add required styles to `body`.
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body
|
||||
// you can use Tailwind CSS too
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: '100vh',
|
||||
}}
|
||||
>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Styles
|
||||
|
||||
Setup Tailwind CSS v4 on your Next.js app, add the following to `global.css`.
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* path of `fumadocs-ui` relative to the CSS file */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
> It doesn't come with a default font, you may choose one from `next/font`.
|
||||
|
||||
### Layout
|
||||
|
||||
Create a `app/layout.config.tsx` file to put the shared options for our layouts.
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/layout.config.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/layout.config.tsx\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Create a folder `/app/docs` for our docs, and give it a proper layout.
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/docs/layout.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/layout.tsx\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> `pageTree` refers to Page Tree, it should be provided by your content source.
|
||||
|
||||
### Page
|
||||
|
||||
Create a catch-all route `/app/docs/[[...slug]]` for docs pages.
|
||||
|
||||
In the page, wrap your content in the [Page](/docs/layouts/page) component.
|
||||
It may vary depending on your content source. You should configure static rendering with `generateStaticParams` and metadata with `generateMetadata`.
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/docs/[[...slug]]/page.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Fumadocs MDX\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value='Content Collections'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/content-collections/app/docs/[[...slug]]/page.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Content Collections\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### Search
|
||||
|
||||
Use the default document search based on Orama.
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/api/search/route.ts",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/api/search/route.ts\" tab=\"Fumadocs MDX\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value='Content Collections'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/content-collections/app/api/search/route.ts",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/api/search/route.ts\" tab=\"Content Collections\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
Learn more about [Document Search](/docs/headless/search).
|
||||
|
||||
### Done
|
||||
|
||||
You can start the dev server and create MDX files.
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
I love Anime.
|
||||
```
|
||||
|
||||
## Customise
|
||||
|
||||
You can use [Home Layout](/docs/layouts/home-layout) for other pages of the site, it includes a navbar with theme toggle.
|
||||
|
||||
## Deploying
|
||||
|
||||
It should work out-of-the-box with Vercel & Netlify.
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
If you want to deploy your Fumadocs app using Docker with **Fumadocs MDX configured**, make sure to add the `source.config.ts` file to the `WORKDIR` in the Dockerfile.
|
||||
The following snippet is taken from the official [Next.js Dockerfile Example](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile):
|
||||
|
||||
```zsh title="Dockerfile"
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
|
||||
```
|
||||
|
||||
This ensures Fumadocs MDX can access your configuration file during builds.
|
196
content/blog/manual-installation.zh.mdx
Normal file
196
content/blog/manual-installation.zh.mdx
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
title: 手动安装
|
||||
description: 从零开始创建一个新的 Fumadocs 项目
|
||||
image: /images/blog/post-4.png
|
||||
date: "2025-03-14"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
> 请先阅读[快速入门](/docs)指南了解基本概念。
|
||||
|
||||
## 入门
|
||||
|
||||
使用 `create-next-app` 创建一个新的 Next.js 应用程序,并安装所需的包。
|
||||
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
### 内容源
|
||||
|
||||
Fumadocs 支持不同的内容源,您可以选择您喜欢的一种。
|
||||
|
||||
以下是官方支持的源列表:
|
||||
|
||||
- [设置 Fumadocs MDX](/docs/mdx)
|
||||
- [设置 Content Collections](/docs/headless/content-collections)
|
||||
|
||||
请确保在继续之前按照其设置指南正确配置库,我们将在本指南中使用 `@/lib/source.ts` 导入源适配器。
|
||||
|
||||
### 根布局
|
||||
|
||||
将整个应用程序包装在 [Root Provider](/docs/layouts/root-provider) 中,并为 `body` 添加所需的样式。
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body
|
||||
// you can use Tailwind CSS too
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: '100vh',
|
||||
}}
|
||||
>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 样式
|
||||
|
||||
在您的 Next.js 应用程序上设置 Tailwind CSS v4,将以下内容添加到 `global.css`。
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* path of `fumadocs-ui` relative to the CSS file */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
> 它不附带默认字体,您可以从 `next/font` 中选择一个。
|
||||
|
||||
### 布局
|
||||
|
||||
创建一个 `app/layout.config.tsx` 文件,放置我们布局的共享选项。
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/layout.config.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/layout.config.tsx\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为我们的文档创建一个文件夹 `/app/docs`,并给它一个适当的布局。
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/docs/layout.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/layout.tsx\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> `pageTree` 指的是页面树,应该由您的内容源提供。
|
||||
|
||||
### 页面
|
||||
|
||||
为文档页面创建一个捕获所有路由 `/app/docs/[[...slug]]`。
|
||||
|
||||
在页面中,将您的内容包装在 [Page](/docs/layouts/page) 组件中。
|
||||
这可能因您的内容源而异。您应该使用 `generateStaticParams` 配置静态渲染,并使用 `generateMetadata` 配置元数据。
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/docs/[[...slug]]/page.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Fumadocs MDX\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value='Content Collections'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/content-collections/app/docs/[[...slug]]/page.tsx",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Content Collections\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 搜索
|
||||
|
||||
使用基于 Orama 的默认文档搜索。
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/next-mdx/app/api/search/route.ts",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/api/search/route.ts\" tab=\"Fumadocs MDX\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value='Content Collections'>
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/content-collections/app/api/search/route.ts",
|
||||
"codeblock": {
|
||||
"meta": "title=\"app/api/search/route.ts\" tab=\"Content Collections\""
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
了解更多关于[文档搜索](/docs/headless/search)的信息。
|
||||
|
||||
### 完成
|
||||
|
||||
您可以启动开发服务器并创建 MDX 文件。
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
I love Anime.
|
||||
```
|
||||
|
||||
## 自定义
|
||||
|
||||
您可以为网站的其他页面使用 [Home Layout](/docs/layouts/home-layout),它包含一个带有主题切换的导航栏。
|
||||
|
||||
## 部署
|
||||
|
||||
它应该在 Vercel 和 Netlify 上开箱即用。
|
||||
|
||||
### Docker 部署
|
||||
|
||||
如果您想使用 Docker 部署您的 Fumadocs 应用程序,并且已**配置了 Fumadocs MDX**,请确保将 `source.config.ts` 文件添加到 Dockerfile 中的 `WORKDIR`。
|
||||
以下片段取自官方 [Next.js Dockerfile 示例](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile):
|
||||
|
||||
```zsh title="Dockerfile"
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
|
||||
```
|
||||
|
||||
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。
|
385
content/blog/markdown.mdx
Normal file
385
content/blog/markdown.mdx
Normal file
@ -0,0 +1,385 @@
|
||||
---
|
||||
title: Markdown
|
||||
description: How to write documents
|
||||
image: /images/blog/post-5.png
|
||||
date: "2025-03-05"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Fumadocs provides many useful extensions to MDX, a markup language. Here is a brief introduction to the default MDX syntax of Fumadocs UI.
|
||||
|
||||
> MDX is not the only supported format of Fumadocs. In fact, you can use any renderers such as `next-mdx-remote` or CMS.
|
||||
|
||||
## Markdown
|
||||
|
||||
We use GFM (GitHub Flavored Markdown), a superset of Markdown (CommonMark).
|
||||
See [GFM Specification](https://github.github.com/gfm).
|
||||
|
||||
````md
|
||||
# Heading
|
||||
|
||||
## Heading
|
||||
|
||||
### Heading
|
||||
|
||||
#### Heading
|
||||
|
||||
Hello World, **Bold**, _Italic_, ~~Hidden~~
|
||||
|
||||
```js
|
||||
console.log('Hello World');
|
||||
```
|
||||
|
||||
1. First
|
||||
2. Second
|
||||
3. Third
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
|
||||
> Quote here
|
||||
|
||||

|
||||
|
||||
| Table | Description |
|
||||
| ----- | ----------- |
|
||||
| Hello | World |
|
||||
````
|
||||
|
||||
### Auto Links
|
||||
|
||||
Internal links use the `next/link` component to allow prefetching and avoid hard-reload.
|
||||
|
||||
External links will get the default `rel="noreferrer noopener" target="_blank"` attributes for security.
|
||||
|
||||
```mdx
|
||||
[My Link](https://github.github.com/gfm)
|
||||
|
||||
This also works: https://github.github.com/gfm.
|
||||
```
|
||||
|
||||
## MDX
|
||||
|
||||
MDX is a superset of Markdown, with support of JSX syntax.
|
||||
It allows you to import components, and use them right in the document, or even export values.
|
||||
|
||||
```mdx
|
||||
import { Component } from './component';
|
||||
|
||||
<Component name="Hello" />
|
||||
```
|
||||
|
||||
see [MDX Syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) to learn more.
|
||||
|
||||
### Cards
|
||||
|
||||
Useful for adding links, it is included by default.
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
>
|
||||
Learn more about caching in Next.js
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
>
|
||||
Learn more about caching in Next.js
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
#### Icon
|
||||
|
||||
You can specify an icon to cards.
|
||||
|
||||
```mdx
|
||||
import { HomeIcon } from 'lucide-react';
|
||||
|
||||
<Cards>
|
||||
<Card icon={<HomeIcon />} href="/" title="Home">
|
||||
Go back to home
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card icon={<HomeIcon />} href="/" title="Go back to home">
|
||||
The home page of Fumadocs.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
#### Without href
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
<Card title="Fetching, Caching, and Revalidating">
|
||||
Learn more about `fetch` in Next.js.
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card title="Fetching, Caching, and Revalidating">
|
||||
Learn more about `fetch` in Next.js.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Callouts
|
||||
|
||||
Useful for adding tips/warnings, it is included by default.
|
||||
|
||||
```mdx
|
||||
<Callout>Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout>Hello World</Callout>
|
||||
|
||||
#### Title
|
||||
|
||||
Specify a callout title.
|
||||
|
||||
```mdx
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
|
||||
#### Types
|
||||
|
||||
You can specify the type of callout.
|
||||
|
||||
- `info` (default)
|
||||
- `warn`
|
||||
- `error`
|
||||
|
||||
```mdx
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
|
||||
### Customise Components
|
||||
|
||||
See [all MDX components and available options](/docs/mdx).
|
||||
|
||||
## Headings
|
||||
|
||||
An anchor is automatically applied to each heading, it sanitizes invalid characters like spaces. (e.g. `Hello World` to `hello-world`)
|
||||
|
||||
```md
|
||||
# Hello `World`
|
||||
```
|
||||
|
||||
### TOC Settings
|
||||
|
||||
The table of contents (TOC) will be generated based on headings, you can also customise the effects of headings:
|
||||
|
||||
```md
|
||||
# Heading [!toc]
|
||||
|
||||
This heading will be hidden from TOC.
|
||||
|
||||
# Another Heading [toc]
|
||||
|
||||
This heading will **only** be visible in TOC, you can use it to add additional TOC items.
|
||||
Like headings rendered in a React component:
|
||||
|
||||
<MyComp />
|
||||
```
|
||||
|
||||
### Custom Anchor
|
||||
|
||||
You can add `[#slug]` to customise heading anchors.
|
||||
|
||||
```md
|
||||
# heading [#my-heading-id]
|
||||
```
|
||||
|
||||
You can also chain it with TOC settings like:
|
||||
|
||||
```md
|
||||
# heading [toc] [#my-heading-id]
|
||||
```
|
||||
|
||||
To link people to a specific heading, add the heading id to hash fragment: `/page#my-heading-id`.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
We support YAML frontmatter. It is a way to specify common information of the document (e.g. title).
|
||||
Place it at the top of document.
|
||||
|
||||
```mdx
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Title
|
||||
```
|
||||
|
||||
See [Page Conventions](/docs/page-conventions#frontmatter) for a list of properties available for frontmatter.
|
||||
|
||||
## Codeblock
|
||||
|
||||
Syntax Highlighting is supported by default using [Rehype Code](/docs/headless/mdx/rehype-code).
|
||||
|
||||
````mdx
|
||||
```js
|
||||
console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
You can add a title to the codeblock.
|
||||
|
||||
````mdx
|
||||
```js title="My Title"
|
||||
console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
### Highlight Lines
|
||||
|
||||
You can highlight specific lines by adding `[!code highlight]`.
|
||||
|
||||
````md
|
||||
```tsx
|
||||
<div>Hello World</div> // [\!code highlight]
|
||||
<div>Hello World</div>
|
||||
<div>Goodbye</div>
|
||||
<div>Hello World</div>
|
||||
```
|
||||
````
|
||||
|
||||
### Highlight Words
|
||||
|
||||
You can highlight a specific word by adding `[!code word:<match>]`.
|
||||
|
||||
````md
|
||||
```js
|
||||
// [\!code word:config]
|
||||
const config = {
|
||||
reactStrictMode: true,
|
||||
};
|
||||
```
|
||||
````
|
||||
|
||||
### Diffs
|
||||
|
||||
````mdx
|
||||
```ts
|
||||
console.log('hewwo'); // [\!code --]
|
||||
console.log('hello'); // [\!code ++]
|
||||
```
|
||||
````
|
||||
|
||||
```ts
|
||||
console.log('hewwo'); // [!code --]
|
||||
console.log('hello'); // [!code ++]
|
||||
```
|
||||
|
||||
### Tab Groups
|
||||
|
||||
You can use code blocks with the `<Tab />` component.
|
||||
|
||||
````mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Tab 1', 'Tab 2']}>
|
||||
<Tab value='Tab 1'>
|
||||
```ts
|
||||
console.log('A');
|
||||
```
|
||||
</Tab>
|
||||
<Tab value='Tab 2'>
|
||||
```ts
|
||||
console.log('B');
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
````
|
||||
|
||||
> Note that you can add MDX components instead of importing them in MDX files.
|
||||
|
||||
<Tabs items={['Tab 1', 'Tab 2']}>
|
||||
<Tab value='Tab 1'>
|
||||
```ts
|
||||
console.log('A');
|
||||
```
|
||||
</Tab>
|
||||
<Tab value='Tab 2'>
|
||||
```ts
|
||||
console.log('B');
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Using Typescript Twoslash
|
||||
|
||||
Write Typescript codeblocks with hover type information and detected types errors.
|
||||
|
||||
Not enabled by default. See [Twoslash](/docs/twoslash).
|
||||
|
||||
## Images
|
||||
|
||||
All built-in content sources handle images properly.
|
||||
Images are automatically optimized for `next/image`.
|
||||
|
||||
```mdx
|
||||

|
||||
```
|
||||
|
||||

|
||||
|
||||
## Optional
|
||||
|
||||
Some optional plugins you can enable.
|
||||
|
||||
### Math Equations
|
||||
|
||||
Write math equations with TeX.
|
||||
|
||||
````md
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
````
|
||||
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
|
||||
To enable, see [Math Integration](/docs/math).
|
||||
|
||||
### Package Install
|
||||
|
||||
Generate code blocks for installing packages via package managers (JS/Node.js).
|
||||
|
||||
````md
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
````
|
||||
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
|
||||
To enable, see [Remark Install](/docs/headless/mdx/install).
|
||||
|
||||
### More
|
||||
|
||||
You can see [a list of plugins](/docs/headless/mdx) supported by Fumadocs.
|
345
content/blog/markdown.zh.mdx
Normal file
345
content/blog/markdown.zh.mdx
Normal file
@ -0,0 +1,345 @@
|
||||
---
|
||||
title: Markdown
|
||||
description: 如何撰写文档
|
||||
image: /images/blog/post-5.png
|
||||
date: "2025-03-05"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 介绍
|
||||
|
||||
Fumadocs 为 MDX(一种标记语言)提供了许多有用的扩展。以下是 Fumadocs UI 默认 MDX 语法的简要介绍。
|
||||
|
||||
> MDX 不是 Fumadocs 唯一支持的格式。实际上,您可以使用任何渲染器,如 `next-mdx-remote` 或 CMS。
|
||||
|
||||
## Markdown
|
||||
|
||||
我们使用 GFM(GitHub 风格的 Markdown),这是 Markdown(CommonMark)的超集。
|
||||
参见 [GFM 规范](https://github.github.com/gfm)。
|
||||
|
||||
````md
|
||||
# Heading
|
||||
|
||||
## Heading
|
||||
|
||||
### Heading
|
||||
|
||||
#### Heading
|
||||
|
||||
Hello World, **Bold**, _Italic_, ~~Hidden~~
|
||||
|
||||
```js
|
||||
console.log('Hello World');
|
||||
```
|
||||
|
||||
1. First
|
||||
2. Second
|
||||
3. Third
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
|
||||
> Quote here
|
||||
|
||||

|
||||
|
||||
| Table | Description |
|
||||
| ----- | ----------- |
|
||||
| Hello | World |
|
||||
````
|
||||
|
||||
### 自动链接
|
||||
|
||||
内部链接使用 `next/link` 组件,允许预取并避免硬重载。
|
||||
|
||||
外部链接将获得默认的 `rel="noreferrer noopener" target="_blank"` 属性以增强安全性。
|
||||
|
||||
```mdx
|
||||
[My Link](https://github.github.com/gfm)
|
||||
|
||||
This also works: https://github.github.com/gfm.
|
||||
```
|
||||
|
||||
## MDX
|
||||
|
||||
MDX 是 Markdown 的超集,支持 JSX 语法。
|
||||
它允许您导入组件,并直接在文档中使用它们,甚至导出值。
|
||||
|
||||
```mdx
|
||||
import { Component } from './component';
|
||||
|
||||
<Component name="Hello" />
|
||||
```
|
||||
|
||||
参见 [MDX 语法](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) 了解更多信息。
|
||||
|
||||
### 卡片
|
||||
|
||||
对于添加链接很有用,默认包含。
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
>
|
||||
Learn more about caching in Next.js
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
>
|
||||
Learn more about caching in Next.js
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
#### 图标
|
||||
|
||||
您可以为卡片指定图标。
|
||||
|
||||
```mdx
|
||||
import { HomeIcon } from 'lucide-react';
|
||||
|
||||
<Cards>
|
||||
<Card icon={<HomeIcon />} href="/" title="Home">
|
||||
Go back to home
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card icon={<HomeIcon />} href="/" title="Go back to home">
|
||||
The home page of Fumadocs.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
#### 无 href
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
<Card title="Fetching, Caching, and Revalidating">
|
||||
Learn more about `fetch` in Next.js.
|
||||
</Card>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card title="Fetching, Caching, and Revalidating">
|
||||
Learn more about `fetch` in Next.js.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### 提示框
|
||||
|
||||
对于添加提示/警告很有用,默认包含。
|
||||
|
||||
```mdx
|
||||
<Callout>Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout>Hello World</Callout>
|
||||
|
||||
#### 标题
|
||||
|
||||
指定提示框标题。
|
||||
|
||||
```mdx
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
|
||||
#### 类型
|
||||
|
||||
您可以指定提示框的类型。
|
||||
|
||||
- `info`(默认)
|
||||
- `warn`
|
||||
- `error`
|
||||
|
||||
```mdx
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
|
||||
### 自定义组件
|
||||
|
||||
参见[所有 MDX 组件和可用选项](/docs/mdx)。
|
||||
|
||||
## 标题
|
||||
|
||||
每个标题会自动应用锚点,它会清理空格等无效字符。(例如,`Hello World` 变为 `hello-world`)
|
||||
|
||||
```md
|
||||
# Hello `World`
|
||||
```
|
||||
|
||||
### 目录设置
|
||||
|
||||
目录 (TOC) 将基于标题生成,您还可以自定义标题的效果:
|
||||
|
||||
```md
|
||||
# Heading [!toc]
|
||||
|
||||
This heading will be hidden from TOC.
|
||||
|
||||
# Another Heading [toc]
|
||||
|
||||
This heading will **only** be visible in TOC, you can use it to add additional TOC items.
|
||||
Like headings rendered in a React component:
|
||||
|
||||
<MyComp />
|
||||
```
|
||||
|
||||
### 自定义锚点
|
||||
|
||||
您可以添加 `[#slug]` 来自定义标题锚点。
|
||||
|
||||
```md
|
||||
# heading [#my-heading-id]
|
||||
```
|
||||
|
||||
您也可以将其与目录设置链接起来,例如:
|
||||
|
||||
```md
|
||||
# heading [toc] [#my-heading-id]
|
||||
```
|
||||
|
||||
要将人们链接到特定标题,请将标题 ID 添加到哈希片段:`/page#my-heading-id`。
|
||||
|
||||
## 前言
|
||||
|
||||
我们支持 YAML 前言。这是一种指定文档常见信息(例如标题)的方式。
|
||||
将其放在文档顶部。
|
||||
|
||||
```mdx
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Title
|
||||
```
|
||||
|
||||
有关前言可用属性的列表,请参见[页面约定](/docs/page-conventions#frontmatter)。
|
||||
|
||||
## 代码块
|
||||
|
||||
默认使用 [Rehype Code](/docs/headless/mdx/rehype-code) 支持语法高亮。
|
||||
|
||||
````mdx
|
||||
```js
|
||||
console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
您可以为代码块添加标题。
|
||||
|
||||
````mdx
|
||||
```js title="My Title"
|
||||
console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
### 高亮行
|
||||
|
||||
````md
|
||||
```tsx
|
||||
<div>Hello World</div> // [\!code highlight]
|
||||
<div>Hello World</div>
|
||||
<div>Goodbye</div>
|
||||
<div>Hello World</div>
|
||||
```
|
||||
````
|
||||
|
||||
### 高亮单词
|
||||
|
||||
您可以通过添加 `[!code word:<match>]` 来高亮特定单词。
|
||||
|
||||
````md
|
||||
```js
|
||||
// [\!code word:config]
|
||||
const config = {
|
||||
reactStrictMode: true,
|
||||
};
|
||||
```
|
||||
````
|
||||
|
||||
### 差异
|
||||
|
||||
````mdx
|
||||
```ts
|
||||
console.log('hewwo'); // [\!code --]
|
||||
console.log('hello'); // [\!code ++]
|
||||
```
|
||||
````
|
||||
|
||||
```ts
|
||||
console.log('hewwo'); // [!code --]
|
||||
console.log('hello'); // [!code ++]
|
||||
```
|
||||
|
||||
### 标签组
|
||||
|
||||
您可以使用 `<Tab />` 组件与代码块一起使用。
|
||||
|
||||
````mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Tab 1', 'Tab 2']}>
|
||||
<Tab value='Tab 1'>
|
||||
```ts
|
||||
console.log('A');
|
||||
```
|
||||
</Tab>
|
||||
<Tab value='Tab 2'>
|
||||
```ts
|
||||
console.log('B');
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
````
|
||||
|
||||
> 注意,您可以在 MDX 文件中添加 MDX 组件,而不必导入它们。
|
||||
|
||||
<Tabs items={['Tab 1', 'Tab 2']}>
|
||||
<Tab value='Tab 1'>
|
||||
```ts
|
||||
console.log('A');
|
||||
```
|
||||
</Tab>
|
||||
<Tab value='Tab 2'>
|
||||
```ts
|
||||
console.log('B');
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 使用 Typescript Twoslash
|
||||
|
||||
编写带有悬停类型信息和检测到类型错误的 Typescript 代码块。
|
||||
|
||||
默认情况下未启用。参见 [Twoslash](/docs/twoslash)。
|
||||
|
||||
## 图片
|
||||
|
||||
所有内置内容源都能正确处理图片。
|
||||
图片会自动为 `next/image` 优化。
|
||||
|
||||
```mdx
|
||||

|
||||
```
|
||||
|
||||
## 可选功能
|
||||
|
||||
一些您可以启用的可选插件。
|
56
content/blog/premium.mdx
Normal file
56
content/blog/premium.mdx
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "Premium Blog Post"
|
||||
description: "This blog post is a test for premium content."
|
||||
date: "2025-08-30"
|
||||
published: true
|
||||
premium: true
|
||||
categories: ["product"]
|
||||
author: "fox"
|
||||
image: "/images/blog/post-7.png"
|
||||
---
|
||||
|
||||
This blog post is a test for premium content.
|
||||
|
||||
You can read this part of the blog post if you are not a premium user.
|
||||
|
||||
But for the rest of the blog post, you need to be logged in as a premium user.
|
||||
|
||||
You can click the "Sign In" button to sign in as a user with free plan.
|
||||
|
||||
Then you can click the "Upgrade Now" button to upgrade to a premium plan.
|
||||
|
||||
<Callout type="warn">
|
||||
Don't worry, you don't actually pay any cents, because we are in the sandbox environment of Stripe.
|
||||
</Callout>
|
||||
|
||||
You can use the test card number to pay for monthly or yearly PRO plan or LIFETIME plan.
|
||||
|
||||
```
|
||||
Card number: 4242 4242 4242 4242
|
||||
Exp: 12/34
|
||||
CVV: 567
|
||||
```
|
||||
|
||||
After that, you can return to the blog post and you can read the rest of the blog post.
|
||||
|
||||
For more details, please check out the documentation: [Blog](https://mksaas.com/docs/blog).
|
||||
|
||||
Now the rest of the blog post is premium content.
|
||||
|
||||
<PremiumContent>
|
||||
|
||||
<Callout type="info">
|
||||
This is the beginning of the premium content part.
|
||||
</Callout>
|
||||
|
||||
This is the premium content part.
|
||||
|
||||
You can read this paragraph only if you are a premium user.
|
||||
|
||||
Please don't share this blog post with others.
|
||||
|
||||
<Callout type="info">
|
||||
This is the end of the premium content part.
|
||||
</Callout>
|
||||
|
||||
</PremiumContent>
|
56
content/blog/premium.zh.mdx
Normal file
56
content/blog/premium.zh.mdx
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "测试专用付费文章"
|
||||
description: "这是一篇测试专用付费文章。"
|
||||
date: "2025-08-30"
|
||||
published: true
|
||||
premium: true
|
||||
categories: ["product"]
|
||||
author: "fox"
|
||||
image: "/images/blog/post-7.png"
|
||||
---
|
||||
|
||||
这是一篇测试专用的付费文章。
|
||||
|
||||
如果你不是付费用户,你可以阅读这篇文章的这部分内容。
|
||||
|
||||
但如果你想阅读剩下的内容,你需要成为一个付费用户。
|
||||
|
||||
你可以点击 "登录" 按钮来以免费用户的身份登录。
|
||||
|
||||
然后你可以点击 "立即升级" 按钮来升级到付费计划。
|
||||
|
||||
<Callout type="warn">
|
||||
不用担心,你实际上不需要支付任何费用,因为我们处于 Stripe 的沙盒环境中。
|
||||
</Callout>
|
||||
|
||||
你可以使用测试卡号来支付月度或年度 PRO 计划或终身计划。
|
||||
|
||||
```
|
||||
Card number: 4242 4242 4242 4242
|
||||
Exp: 12/34
|
||||
CVV: 567
|
||||
```
|
||||
|
||||
之后,你可以返回这篇博客文章,然后你可以阅读剩下的内容。
|
||||
|
||||
更多详情,请参考文档:[博客](https://mksaas.com/docs/blog)。
|
||||
|
||||
现在剩下的内容是付费内容。
|
||||
|
||||
<PremiumContent>
|
||||
|
||||
<Callout type="info">
|
||||
这是付费内容部分的开始。
|
||||
</Callout>
|
||||
|
||||
这是付费内容部分。
|
||||
|
||||
你可以阅读这篇内容,只要你是一个付费用户。
|
||||
|
||||
请不要分享这篇文章给其他人。
|
||||
|
||||
<Callout type="info">
|
||||
这是付费内容部分的结束。
|
||||
</Callout>
|
||||
|
||||
</PremiumContent>
|
280
content/blog/search.mdx
Normal file
280
content/blog/search.mdx
Normal file
@ -0,0 +1,280 @@
|
||||
---
|
||||
title: Search
|
||||
description: Implement document search in your docs
|
||||
image: /images/blog/post-6.png
|
||||
date: "2025-02-15"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
Fumadocs UI provides a good-looking search UI for your docs, the search functionality is instead provided and documented on Fumadocs Core.
|
||||
|
||||
See [Document Search](/docs/headless/search).
|
||||
|
||||
## Search UI
|
||||
|
||||
Open with <kbd>⌘</kbd> <kbd>K</kbd> or <kbd>Ctrl</kbd> <kbd>K</kbd>.
|
||||
|
||||
### Configurations
|
||||
|
||||
You can customize search UI from the [Root Provider](/docs/layouts/root-provider) component in root layout.
|
||||
|
||||
When not specified, it uses the Default [`fetch` Search Client](/docs/headless/search/orama) powered by Orama.
|
||||
|
||||
### Custom Links
|
||||
|
||||
Add custom link items to search dialog.
|
||||
They are shown as fallbacks when the query is empty.
|
||||
|
||||
```tsx title="app/layout.tsx"
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
links: [
|
||||
['Home', '/'],
|
||||
['Docs', '/docs'],
|
||||
],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### Disable Search
|
||||
|
||||
To opt-out of document search, disable it from root provider.
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
enabled: false,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### Hot Keys
|
||||
|
||||
Customise the hot keys to trigger search dialog.
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
hotKey: [
|
||||
{
|
||||
display: 'K',
|
||||
key: 'k', // key code, or a function determining whether the key is pressed
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### Tag Filter
|
||||
|
||||
Add UI to change filters.
|
||||
Make sure to configure [Tag Filter](/docs/headless/search/orama#tag-filter) on search server first.
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
options: {
|
||||
defaultTag: 'value',
|
||||
tags: [
|
||||
{
|
||||
name: 'Tag Name',
|
||||
value: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### Search Options
|
||||
|
||||
Pass options to the search client, like changing the API endpoint for Orama search server:
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
options: {
|
||||
api: '/api/search/docs',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### Replace Search Dialog
|
||||
|
||||
You can replace the default Search Dialog with:
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-default';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
|
||||
export default function CustomDialog(props: SharedProps) {
|
||||
// your own logic here
|
||||
return <SearchDialog {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
To pass it to the Root Provider, you need a wrapper with `use client` directive.
|
||||
|
||||
```tsx title="provider.tsx"
|
||||
'use client';
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
const SearchDialog = dynamic(() => import('@/components/search')); // lazy load
|
||||
|
||||
export function Provider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<RootProvider
|
||||
search={{
|
||||
SearchDialog,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Use it instead of your previous Root Provider
|
||||
|
||||
```tsx title="layout.tsx"
|
||||
import { Provider } from './provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Provider>{children}</Provider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Other Solutions
|
||||
|
||||
### Algolia
|
||||
|
||||
For the setup guide, see [Integrate Algolia Search](/docs/headless/search/algolia).
|
||||
|
||||
While generally we recommend building your own search with their client-side
|
||||
SDK, you can also plug the built-in dialog interface.
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
import algo from 'algoliasearch/lite';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
|
||||
|
||||
const client = algo('appId', 'apiKey');
|
||||
const index = client.initIndex('indexName');
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
return <SearchDialog index={index} {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
1. Replace `appId`, `apiKey` and `indexName` with your desired values.
|
||||
|
||||
2. [Replace the default search dialog](#replace-search-dialog) with your new component.
|
||||
|
||||
<Callout title="Note" className='mt-4'>
|
||||
|
||||
The built-in implementation doesn't use instant search (their official
|
||||
javascript client).
|
||||
|
||||
</Callout>
|
||||
|
||||
#### Tag Filter
|
||||
|
||||
Same as default search client, you can configure [Tag Filter](/docs/headless/search/algolia#tag-filter) on the dialog.
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
|
||||
|
||||
<SearchDialog
|
||||
defaultTag="value"
|
||||
tags={[
|
||||
{
|
||||
name: 'Tag Name',
|
||||
value: 'value',
|
||||
},
|
||||
]}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Orama Cloud
|
||||
|
||||
For the setup guide, see [Integrate Orama Cloud](/docs/headless/search/orama-cloud).
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
|
||||
import { OramaClient } from '@oramacloud/client';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-orama';
|
||||
|
||||
const client = new OramaClient({
|
||||
endpoint: 'endpoint',
|
||||
api_key: 'apiKey',
|
||||
});
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
return <SearchDialog {...props} client={client} showOrama />;
|
||||
}
|
||||
```
|
||||
|
||||
1. Replace `endpoint`, `apiKey` with your desired values.
|
||||
2. [Replace the default search dialog](#replace-search-dialog) with your new component.
|
||||
|
||||
### Community Integrations
|
||||
|
||||
A list of integrations maintained by community.
|
||||
|
||||
- [Trieve Search](/docs/headless/search/trieve)
|
||||
|
||||
## Built-in UI
|
||||
|
||||
If you want to use the built-in search dialog UI instead of building your own,
|
||||
you may use the `SearchDialog` component.
|
||||
|
||||
```tsx
|
||||
import {
|
||||
SearchDialog,
|
||||
type SharedProps,
|
||||
} from 'fumadocs-ui/components/dialog/search';
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
return <SearchDialog {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
<Callout type="warn" title="Unstable">
|
||||
It is an internal API, might break during iterations
|
||||
</Callout>
|
252
content/blog/search.zh.mdx
Normal file
252
content/blog/search.zh.mdx
Normal file
@ -0,0 +1,252 @@
|
||||
---
|
||||
title: 搜索
|
||||
description: 在您的文档中实现文档搜索
|
||||
image: /images/blog/post-6.png
|
||||
date: "2025-02-15"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
Fumadocs UI 为您的文档提供了一个美观的搜索界面,而搜索功能则由 Fumadocs Core 提供和记录。
|
||||
|
||||
参见[文档搜索](/docs/headless/search)。
|
||||
|
||||
## 搜索 UI
|
||||
|
||||
使用 <kbd>⌘</kbd> <kbd>K</kbd> 或 <kbd>Ctrl</kbd> <kbd>K</kbd> 打开。
|
||||
|
||||
### 配置
|
||||
|
||||
您可以通过根布局中的 [Root Provider](/docs/layouts/root-provider) 组件自定义搜索 UI。
|
||||
|
||||
当未指定时,它使用由 Orama 提供支持的默认 [`fetch` 搜索客户端](/docs/headless/search/orama)。
|
||||
|
||||
### 自定义链接
|
||||
|
||||
向搜索对话框添加自定义链接项。
|
||||
当查询为空时,它们会显示为备选项。
|
||||
|
||||
```tsx title="app/layout.tsx"
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
links: [
|
||||
['Home', '/'],
|
||||
['Docs', '/docs'],
|
||||
],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### 禁用搜索
|
||||
|
||||
要禁用文档搜索,请在根提供程序中禁用它。
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
enabled: false,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### 热键
|
||||
|
||||
自定义触发搜索对话框的热键。
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
hotKey: [
|
||||
{
|
||||
display: 'K',
|
||||
key: 'k', // key code, or a function determining whether the key is pressed
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### 标签过滤器
|
||||
|
||||
添加 UI 以更改过滤器。
|
||||
确保首先在搜索服务器上配置[标签过滤器](/docs/headless/search/orama#tag-filter)。
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
options: {
|
||||
defaultTag: 'value',
|
||||
tags: [
|
||||
{
|
||||
name: 'Tag Name',
|
||||
value: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### 搜索选项
|
||||
|
||||
向搜索客户端传递选项,例如更改 Orama 搜索服务器的 API 端点:
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/root-provider';
|
||||
|
||||
<RootProvider
|
||||
search={{
|
||||
options: {
|
||||
api: '/api/search/docs',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>;
|
||||
```
|
||||
|
||||
### 替换搜索对话框
|
||||
|
||||
您可以用以下内容替换默认搜索对话框:
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-default';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
|
||||
export default function CustomDialog(props: SharedProps) {
|
||||
// your own logic here
|
||||
return <SearchDialog {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
要将其传递给 Root Provider,您需要一个带有 `use client` 指令的包装器。
|
||||
|
||||
```tsx title="provider.tsx"
|
||||
'use client';
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
const SearchDialog = dynamic(() => import('@/components/search')); // lazy load
|
||||
|
||||
export function Provider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<RootProvider
|
||||
search={{
|
||||
SearchDialog,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
使用它替代您之前的 Root Provider
|
||||
|
||||
```tsx title="layout.tsx"
|
||||
import { Provider } from './provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Provider>{children}</Provider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 其他解决方案
|
||||
|
||||
### Algolia
|
||||
|
||||
关于设置指南,请参见[集成 Algolia 搜索](/docs/headless/search/algolia)。
|
||||
|
||||
虽然我们通常建议使用他们的客户端 SDK 构建您自己的搜索,但您也可以插入内置的对话框接口。
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
import algo from 'algoliasearch/lite';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
|
||||
|
||||
const client = algo('appId', 'apiKey');
|
||||
const index = client.initIndex('indexName');
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
return <SearchDialog index={index} {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
1. 将 `appId`、`apiKey` 和 `indexName` 替换为您想要的值。
|
||||
|
||||
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。
|
||||
|
||||
<Callout title="注意" className='mt-4'>
|
||||
|
||||
内置实现不使用即时搜索(他们的官方 JavaScript 客户端)。
|
||||
|
||||
</Callout>
|
||||
|
||||
#### 标签过滤器
|
||||
|
||||
与默认搜索客户端相同,您可以在对话框上配置[标签过滤器](/docs/headless/search/algolia#tag-filter)。
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
|
||||
|
||||
<SearchDialog
|
||||
defaultTag="value"
|
||||
tags={[
|
||||
{
|
||||
name: 'Tag Name',
|
||||
value: 'value',
|
||||
},
|
||||
]}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Orama Cloud
|
||||
|
||||
关于设置指南,请参见[集成 Orama Cloud](/docs/headless/search/orama-cloud)。
|
||||
|
||||
```tsx title="components/search.tsx"
|
||||
'use client';
|
||||
|
||||
import { OramaClient } from '@oramacloud/client';
|
||||
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
|
||||
import SearchDialog from 'fumadocs-ui/components/dialog/search-orama';
|
||||
|
||||
const client = new OramaClient({
|
||||
endpoint: 'endpoint',
|
||||
api_key: 'apiKey',
|
||||
});
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
return <SearchDialog {...props} client={client} showOrama />;
|
||||
}
|
||||
```
|
||||
|
||||
1. 将 `endpoint`、`apiKey` 替换为您想要的值。
|
||||
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。
|
171
content/blog/theme.mdx
Normal file
171
content/blog/theme.mdx
Normal file
@ -0,0 +1,171 @@
|
||||
---
|
||||
title: Themes
|
||||
description: Add Theme to Fumadocs UI
|
||||
image: /images/blog/post-7.png
|
||||
date: "2025-01-15"
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Note only Tailwind CSS v4 is supported:
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* path of `fumadocs-ui` relative to the CSS file */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
### Preflight Changes
|
||||
|
||||
By using the Tailwind CSS plugin, or the pre-built stylesheet, your default border, text and background
|
||||
colors will be changed.
|
||||
|
||||
### Light/Dark Modes
|
||||
|
||||
Fumadocs supports light/dark modes with [`next-themes`](https://github.com/pacocoursey/next-themes), it is included in Root Provider.
|
||||
|
||||
See [Root Provider](/docs/layouts/root-provider#theme-provider) to learn more.
|
||||
|
||||
### RTL Layout
|
||||
|
||||
RTL (Right-to-left) layout is supported.
|
||||
|
||||
To enable RTL, set the `dir` prop to `rtl` in body and root provider (required for Radix UI).
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body dir="rtl">
|
||||
<RootProvider dir="rtl">{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Prefix
|
||||
|
||||
Fumadocs UI has its own colors, animations, and utilities.
|
||||
By default, it adds a `fd-` prefix to avoid conflicts with Shadcn UI or your own CSS variables.
|
||||
|
||||
You can use them without the prefix by adding some aliases:
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@theme {
|
||||
--color-primary: var(--color-fd-primary);
|
||||
}
|
||||
```
|
||||
|
||||
> You can use it with CSS media queries for responsive design.
|
||||
|
||||
### Layout Width
|
||||
|
||||
Customise the max width of docs layout with CSS Variables.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--fd-layout-width: 1400px;
|
||||
}
|
||||
```
|
||||
|
||||
{/* <WidthTrigger /> */}
|
||||
|
||||
## Tailwind CSS Preset
|
||||
|
||||
The Tailwind CSS preset introduces new colors and extra utilities including `fd-steps`.
|
||||
|
||||
### Themes
|
||||
|
||||
It comes with many themes out-of-the-box, you can pick one you prefer.
|
||||
|
||||
```css
|
||||
@import 'fumadocs-ui/css/<theme>.css';
|
||||
|
||||
/* Example */
|
||||
@import 'fumadocs-ui/css/black.css';
|
||||
```
|
||||
|
||||
<Tabs items={['neutral', 'black', 'vitepress', 'dusk', 'catppuccin', 'ocean', 'purple']}>
|
||||
|
||||
<Tab value='neutral'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='black'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='vitepress'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='dusk'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Catppuccin'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='ocean'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='purple'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### Colors
|
||||
|
||||
The design system was inspired by [Shadcn UI](https://ui.shadcn.com), you can easily customize the colors using CSS variables.
|
||||
|
||||
```css title="global.css"
|
||||
:root {
|
||||
--color-fd-background: hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--color-fd-background: hsl(0, 0%, 0%);
|
||||
}
|
||||
```
|
||||
|
||||
### Typography
|
||||
|
||||
We have a built-in plugin forked from [Tailwind CSS Typography](https://tailwindcss.com/docs/typography-plugin).
|
||||
|
||||
The plugin adds a `prose` class and variants to customise it.
|
||||
|
||||
```tsx
|
||||
<div className="prose">
|
||||
<h1>Good Heading</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
> The plugin works with and only with Fumadocs UI's MDX components, it may conflict with `@tailwindcss/typography`.
|
||||
> If you need to use `@tailwindcss/typography` over the default plugin, [set a class name option](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name) to avoid conflicts.
|
170
content/blog/theme.zh.mdx
Normal file
170
content/blog/theme.zh.mdx
Normal file
@ -0,0 +1,170 @@
|
||||
---
|
||||
title: 主题
|
||||
description: 为 Fumadocs UI 添加主题
|
||||
image: /images/blog/post-7.png
|
||||
date: "2025-01-15"
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
注意只支持 Tailwind CSS v4:
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* path of `fumadocs-ui` relative to the CSS file */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
### 预设更改
|
||||
|
||||
通过使用 Tailwind CSS 插件或预构建的样式表,您的默认边框、文本和背景颜色将被更改。
|
||||
|
||||
### 明/暗模式
|
||||
|
||||
Fumadocs 通过 [`next-themes`](https://github.com/pacocoursey/next-themes) 支持明/暗模式,它包含在 Root Provider 中。
|
||||
|
||||
参见 [Root Provider](/docs/layouts/root-provider#theme-provider) 了解更多信息。
|
||||
|
||||
### RTL 布局
|
||||
|
||||
支持 RTL(从右到左)布局。
|
||||
|
||||
要启用 RTL,请在 body 和 root provider(Radix UI 需要)中将 `dir` 属性设置为 `rtl`。
|
||||
|
||||
```tsx
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body dir="rtl">
|
||||
<RootProvider dir="rtl">{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 前缀
|
||||
|
||||
Fumadocs UI 有自己的颜色、动画和工具。
|
||||
默认情况下,它添加了 `fd-` 前缀,以避免与 Shadcn UI 或您自己的 CSS 变量冲突。
|
||||
|
||||
您可以通过添加一些别名来使用它们,而无需前缀:
|
||||
|
||||
```css title="Tailwind CSS"
|
||||
@theme {
|
||||
--color-primary: var(--color-fd-primary);
|
||||
}
|
||||
```
|
||||
|
||||
> 您可以将其与 CSS 媒体查询一起使用,实现响应式设计。
|
||||
|
||||
### 布局宽度
|
||||
|
||||
使用 CSS 变量自定义文档布局的最大宽度。
|
||||
|
||||
```css
|
||||
:root {
|
||||
--fd-layout-width: 1400px;
|
||||
}
|
||||
```
|
||||
|
||||
{/* <WidthTrigger /> */}
|
||||
|
||||
## Tailwind CSS 预设
|
||||
|
||||
Tailwind CSS 预设引入了新的颜色和额外的工具,包括 `fd-steps`。
|
||||
|
||||
### 主题
|
||||
|
||||
它开箱即用地提供了许多主题,您可以选择一个您喜欢的。
|
||||
|
||||
```css
|
||||
@import 'fumadocs-ui/css/<theme>.css';
|
||||
|
||||
/* Example */
|
||||
@import 'fumadocs-ui/css/black.css';
|
||||
```
|
||||
|
||||
<Tabs items={['neutral', 'black', 'vitepress', 'dusk', 'catppuccin', 'ocean', 'purple']}>
|
||||
|
||||
<Tab value='neutral'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='black'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='vitepress'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='dusk'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Catppuccin'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='ocean'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='purple'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### 颜色
|
||||
|
||||
设计系统的灵感来自 [Shadcn UI](https://ui.shadcn.com),您可以使用 CSS 变量轻松自定义颜色。
|
||||
|
||||
```css title="global.css"
|
||||
:root {
|
||||
--color-fd-background: hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--color-fd-background: hsl(0, 0%, 0%);
|
||||
}
|
||||
```
|
||||
|
||||
### 排版
|
||||
|
||||
我们有一个内置插件,它是从 [Tailwind CSS Typography](https://tailwindcss.com/docs/typography-plugin) 派生而来的。
|
||||
|
||||
该插件添加了一个 `prose` 类和变体来自定义它。
|
||||
|
||||
```tsx
|
||||
<div className="prose">
|
||||
<h1>Good Heading</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
> 该插件仅与 Fumadocs UI 的 MDX 组件一起工作,它可能与 `@tailwindcss/typography` 冲突。
|
||||
> 如果您需要使用 `@tailwindcss/typography` 而不是默认插件,请[设置类名选项](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name)以避免冲突。
|
62
content/blog/what-is-fumadocs.mdx
Normal file
62
content/blog/what-is-fumadocs.mdx
Normal file
@ -0,0 +1,62 @@
|
||||
---
|
||||
title: What is Fumadocs
|
||||
description: Introducing Fumadocs, a docs framework that you can break.
|
||||
image: /images/blog/post-1.png
|
||||
date: "2025-04-01"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
---
|
||||
|
||||
Fumadocs was created because I wanted a more customisable experience for building docs, to be a docs framework that is not opinionated, **a "framework" that you can break**.
|
||||
|
||||
## Philosophy
|
||||
|
||||
**Less Abstraction:** Fumadocs expects you to write code and cooperate with the rest of your software.
|
||||
While most frameworks are configured with a configuration file, they usually lack flexibility when you hope to tune its details.
|
||||
You can’t control how they render the page nor the internal logic. Fumadocs shows you how the app works, instead of a single configuration file.
|
||||
|
||||
**Next.js Fundamentals:** It gives you the utilities and a good-looking UI.
|
||||
You are still using features of Next.js App Router, like **Static Site Generation**. There is nothing new for Next.js developers, so you can use it with confidence.
|
||||
|
||||
**Opinionated on UI:** The only thing Fumadocs UI (the default theme) offers is **User Interface**. The UI is opinionated for bringing better mobile responsiveness and user experience.
|
||||
Instead, we use a much more flexible approach inspired by Shadcn UI — [Fumadocs CLI](/docs/cli), so we can iterate our design quick, and welcome for more feedback about the UI.
|
||||
|
||||
## Why Fumadocs
|
||||
|
||||
Fumadocs is designed with flexibility in mind.
|
||||
|
||||
You can use `fumadocs-core` as a headless UI library and bring your own styles.
|
||||
Fumadocs MDX is also a useful library to handle MDX content in Next.js. It also includes:
|
||||
|
||||
- Many built-in components.
|
||||
- Typescript Twoslash, OpenAPI, and Math (KaTeX) integrations.
|
||||
- Fast and optimized by default, natively built on App Router.
|
||||
- Tight integration with Next.js, you can add it to an existing Next.js project easily.
|
||||
|
||||
You can read [Comparisons](/docs/comparisons) if you're interested.
|
||||
|
||||
### Documentation
|
||||
|
||||
Fumadocs focuses on **authoring experience**, it provides a beautiful theme and many docs automation tools.
|
||||
|
||||
It helps you to iterate your codebase faster while never leaving your docs behind.
|
||||
You can take this site as an example of docs site built with Fumadocs.
|
||||
|
||||
### Blog sites
|
||||
|
||||
Since Next.js is already a powerful framework, most features can be implemented with **just Next.js**.
|
||||
|
||||
Fumadocs provides additional tooling for Next.js, including syntax highlighting, document search, and a default theme (Fumadocs UI).
|
||||
It helps you to avoid reinventing the wheels.
|
||||
|
||||
## When to use Fumadocs
|
||||
|
||||
For most of the web applications, vanilla React.js is no longer enough.
|
||||
Nowadays, we also wish to have a blog, a showcase page, a FAQ page, etc. With a
|
||||
fancy UI that's breathtaking, in these cases, Fumadocs can help you build the
|
||||
docs easier, with less boilerplate.
|
||||
|
||||
Fumadocs is maintained by Fuma and many contributors, with care on the maintainability of codebase.
|
||||
While we don't aim to offer every functionality people wanted, we're more focused on making basic features perfect and well-maintained.
|
||||
You can also help Fumadocs to be more useful by contributing!
|
60
content/blog/what-is-fumadocs.zh.mdx
Normal file
60
content/blog/what-is-fumadocs.zh.mdx
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: 什么是 Fumadocs
|
||||
description: 介绍 Fumadocs,一个可以打破常规的文档框架
|
||||
image: /images/blog/post-1.png
|
||||
date: "2025-04-01"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
---
|
||||
|
||||
Fumadocs 的创建是因为我想要一种更加可定制化的文档构建体验,一个不固执己见的文档框架,**一个你可以"打破"的"框架"**。
|
||||
|
||||
## 理念
|
||||
|
||||
**更少的抽象:** Fumadocs 期望您编写代码并与您的其余软件协作。
|
||||
虽然大多数框架都是通过配置文件进行配置,但当您希望调整其细节时,它们通常缺乏灵活性。
|
||||
您无法控制它们如何渲染页面或内部逻辑。Fumadocs 向您展示应用程序如何工作,而不是仅提供单一的配置文件。
|
||||
|
||||
**Next.js 基础:** 它为您提供实用工具和美观的 UI。
|
||||
您仍然使用 Next.js App Router 的功能,如**静态站点生成**。对于 Next.js 开发者来说没有新的东西,所以您可以放心使用。
|
||||
|
||||
**对 UI 有自己的看法:** Fumadocs UI(默认主题)提供的唯一东西是**用户界面**。UI 的设计理念是提供更好的移动响应性和用户体验。
|
||||
相反,我们使用受 Shadcn UI 启发的更灵活的方法 — [Fumadocs CLI](/docs/cli),这样我们可以快速迭代设计,并欢迎更多关于 UI 的反馈。
|
||||
|
||||
## 为什么选择 Fumadocs
|
||||
|
||||
Fumadocs 的设计考虑了灵活性。
|
||||
|
||||
您可以将 `fumadocs-core` 用作无头 UI 库并带来您自己的样式。
|
||||
Fumadocs MDX 也是处理 Next.js 中 MDX 内容的有用库。它还包括:
|
||||
|
||||
- 许多内置组件。
|
||||
- Typescript Twoslash、OpenAPI 和 Math (KaTeX) 集成。
|
||||
- 默认情况下快速且优化,原生构建在 App Router 上。
|
||||
- 与 Next.js 紧密集成,您可以轻松将其添加到现有的 Next.js 项目中。
|
||||
|
||||
如果您感兴趣,可以阅读 [比较](/docs/comparisons)。
|
||||
|
||||
### 文档
|
||||
|
||||
Fumadocs 专注于**创作体验**,它提供了一个漂亮的主题和许多文档自动化工具。
|
||||
|
||||
它帮助您更快地迭代代码库,同时不会落下您的文档。
|
||||
您可以将此站点作为使用 Fumadocs 构建的文档站点的示例。
|
||||
|
||||
### 博客站点
|
||||
|
||||
由于 Next.js 已经是一个强大的框架,大多数功能可以**仅使用 Next.js** 实现。
|
||||
|
||||
Fumadocs 为 Next.js 提供了额外的工具,包括语法高亮、文档搜索和默认主题(Fumadocs UI)。
|
||||
它帮助您避免重新发明轮子。
|
||||
|
||||
## 何时使用 Fumadocs
|
||||
|
||||
对于大多数 Web 应用程序,原生 React.js 已经不够用了。
|
||||
如今,我们还希望有一个博客、展示页面、FAQ 页面等。带有令人惊叹的精美 UI,在这些情况下,Fumadocs 可以帮助您更轻松地构建文档,减少样板代码。
|
||||
|
||||
Fumadocs 由 Fuma 和许多贡献者维护,关注代码库的可维护性。
|
||||
虽然我们不打算提供人们想要的每一项功能,但我们更专注于使基本功能完美且维护良好。
|
||||
您也可以通过贡献来帮助 Fumadocs 变得更加有用!
|
4
content/category/company.mdx
Normal file
4
content/category/company.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Company
|
||||
description: Company news and updates
|
||||
---
|
4
content/category/company.zh.mdx
Normal file
4
content/category/company.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: 公司
|
||||
description: 公司新闻和更新
|
||||
---
|
4
content/category/news.mdx
Normal file
4
content/category/news.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: News
|
||||
description: News and updates about MkSaaS
|
||||
---
|
4
content/category/news.zh.mdx
Normal file
4
content/category/news.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: 新闻
|
||||
description: 最新新闻和更新
|
||||
---
|
4
content/category/product.mdx
Normal file
4
content/category/product.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: Product
|
||||
description: Products and services powered by MkSaaS
|
||||
---
|
4
content/category/product.zh.mdx
Normal file
4
content/category/product.zh.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
name: 产品
|
||||
description: 产品和服务
|
||||
---
|
30
content/changelog/v1-0-0.mdx
Normal file
30
content/changelog/v1-0-0.mdx
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "Initial Release"
|
||||
description: "Our first official release with core features and functionality"
|
||||
date: "2024-03-01"
|
||||
version: "v1.0.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### Core Features
|
||||
|
||||
We're excited to announce the initial release of our platform with the following core features:
|
||||
|
||||
- **User Authentication**: Secure login and registration with email verification
|
||||
- **Dashboard**: Intuitive dashboard for managing your projects and resources
|
||||
- **Project Management**: Create, edit, and organize your projects with ease
|
||||
- **Team Collaboration**: Invite team members and collaborate on projects
|
||||
- **API Integration**: Connect with third-party services through our API
|
||||
|
||||
### Technical Improvements
|
||||
|
||||
- Built with Next.js 14 and React Server Components for optimal performance
|
||||
- Implemented Drizzle ORM for type-safe database operations
|
||||
- Added comprehensive error handling and logging
|
||||
- Optimized for mobile and desktop experiences
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed issues with user registration flow
|
||||
- Resolved authentication token expiration handling
|
||||
- Improved form validation and error messages
|
30
content/changelog/v1-0-0.zh.mdx
Normal file
30
content/changelog/v1-0-0.zh.mdx
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "初始版本"
|
||||
description: "我们的第一个正式版本,包含核心功能"
|
||||
date: "2024-03-01"
|
||||
version: "v1.0.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### 核心功能
|
||||
|
||||
我们很高兴宣布平台的初始版本,包含以下核心功能:
|
||||
|
||||
- **用户认证**:安全的登录和注册,带有电子邮件验证
|
||||
- **仪表盘**:直观的仪表盘,用于管理您的项目和资源
|
||||
- **项目管理**:轻松创建、编辑和组织您的项目
|
||||
- **团队协作**:邀请团队成员并在项目上协作
|
||||
- **API集成**:通过我们的API连接第三方服务
|
||||
|
||||
### 技术改进
|
||||
|
||||
- 使用Next.js 14和React服务器组件构建,以获得最佳性能
|
||||
- 实现Drizzle ORM进行类型安全的数据库操作
|
||||
- 添加全面的错误处理和日志记录
|
||||
- 针对移动和桌面体验进行优化
|
||||
|
||||
### 错误修复
|
||||
|
||||
- 修复了用户注册流程中的问题
|
||||
- 解决了身份验证令牌过期处理
|
||||
- 改进了表单验证和错误消息
|
30
content/changelog/v1-1-0.mdx
Normal file
30
content/changelog/v1-1-0.mdx
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "Feature Update"
|
||||
description: "New features and improvements to enhance your experience"
|
||||
date: "2024-03-15"
|
||||
version: "v1.1.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### New Features
|
||||
|
||||
We've added several new features to improve your experience:
|
||||
|
||||
- **Dark Mode**: Toggle between light and dark themes based on your preference
|
||||
- **Export Options**: Export your data in multiple formats (CSV, JSON, PDF)
|
||||
- **Advanced Search**: Find what you need faster with our improved search functionality
|
||||
- **Custom Templates**: Create and save templates for recurring projects
|
||||
|
||||
### Enhancements
|
||||
|
||||
- **Performance Optimization**: Reduced page load times by 40%
|
||||
- **UI Improvements**: Refreshed design with better accessibility
|
||||
- **Mobile Experience**: Enhanced responsive design for all device sizes
|
||||
- **Notification System**: Improved notification delivery and management
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed issue with project duplication
|
||||
- Resolved calendar sync problems
|
||||
- Fixed data import validation errors
|
||||
- Improved error handling for API requests
|
30
content/changelog/v1-1-0.zh.mdx
Normal file
30
content/changelog/v1-1-0.zh.mdx
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "功能更新"
|
||||
description: "新功能和改进,提升您的使用体验"
|
||||
date: "2024-03-15"
|
||||
version: "v1.1.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### 新功能
|
||||
|
||||
我们添加了几个新功能来改善您的体验:
|
||||
|
||||
- **深色模式**:根据您的偏好在浅色和深色主题之间切换
|
||||
- **导出选项**:以多种格式(CSV、JSON、PDF)导出您的数据
|
||||
- **高级搜索**:通过我们改进的搜索功能更快地找到您需要的内容
|
||||
- **自定义模板**:为重复项目创建和保存模板
|
||||
|
||||
### 增强功能
|
||||
|
||||
- **性能优化**:页面加载时间减少40%
|
||||
- **UI改进**:更新设计,提高可访问性
|
||||
- **移动体验**:为所有设备尺寸增强响应式设计
|
||||
- **通知系统**:改进通知传递和管理
|
||||
|
||||
### 错误修复
|
||||
|
||||
- 修复了项目复制问题
|
||||
- 解决了日历同步问题
|
||||
- 修复了数据导入验证错误
|
||||
- 改进了API请求的错误处理
|
37
content/changelog/v1-2-0.mdx
Normal file
37
content/changelog/v1-2-0.mdx
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "AI Integration"
|
||||
description: "Introducing AI-powered features to boost productivity"
|
||||
date: "2024-03-30"
|
||||
version: "v1.2.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### AI-Powered Features
|
||||
|
||||
We're thrilled to introduce our new AI capabilities:
|
||||
|
||||
- **Smart Suggestions**: Get intelligent recommendations based on your usage patterns
|
||||
- **Content Generation**: Generate high-quality content with our AI assistant
|
||||
- **Automated Tagging**: Let AI organize your content with smart tagging
|
||||
- **Predictive Analytics**: Forecast trends and outcomes with AI-powered insights
|
||||
|
||||
### Platform Improvements
|
||||
|
||||
- **Webhooks**: Set up custom webhooks to integrate with your workflow
|
||||
- **Enhanced Security**: Added two-factor authentication and improved password policies
|
||||
- **Custom Domains**: Use your own domain for your workspace
|
||||
- **Audit Logs**: Track all activities with comprehensive audit logging
|
||||
|
||||
### Developer Tools
|
||||
|
||||
- **Expanded API**: New endpoints for advanced integrations
|
||||
- **SDK Updates**: Updated SDKs for all major programming languages
|
||||
- **Developer Console**: Improved developer experience with better documentation
|
||||
- **Rate Limiting Controls**: Manage API usage with flexible rate limiting
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed issues with file uploads on certain browsers
|
||||
- Resolved synchronization issues between devices
|
||||
- Improved error handling for third-party integrations
|
||||
- Fixed accessibility issues in the dashboard
|
37
content/changelog/v1-2-0.zh.mdx
Normal file
37
content/changelog/v1-2-0.zh.mdx
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "AI集成"
|
||||
description: "引入AI驱动的功能,提高生产力"
|
||||
date: "2024-03-30"
|
||||
version: "v1.2.0"
|
||||
published: true
|
||||
---
|
||||
|
||||
### AI驱动功能
|
||||
|
||||
我们很高兴介绍我们的新AI功能:
|
||||
|
||||
- **智能建议**:根据您的使用模式获取智能推荐
|
||||
- **内容生成**:使用我们的AI助手生成高质量内容
|
||||
- **自动标记**:让AI通过智能标记组织您的内容
|
||||
- **预测分析**:使用AI驱动的洞察力预测趋势和结果
|
||||
|
||||
### 平台改进
|
||||
|
||||
- **Webhooks**:设置自定义webhooks以集成到您的工作流程中
|
||||
- **增强安全性**:添加双因素认证和改进的密码策略
|
||||
- **自定义域名**:为您的工作空间使用自己的域名
|
||||
- **审计日志**:通过全面的审计日志跟踪所有活动
|
||||
|
||||
### 开发者工具
|
||||
|
||||
- **扩展API**:用于高级集成的新端点
|
||||
- **SDK更新**:更新了所有主要编程语言的SDK
|
||||
- **开发者控制台**:通过更好的文档改善开发者体验
|
||||
- **速率限制控制**:通过灵活的速率限制管理API使用
|
||||
|
||||
### 错误修复
|
||||
|
||||
- 修复了某些浏览器上文件上传的问题
|
||||
- 解决了设备之间的同步问题
|
||||
- 改进了第三方集成的错误处理
|
||||
- 修复了仪表板中的可访问性问题
|
74
content/docs/comparisons.mdx
Normal file
74
content/docs/comparisons.mdx
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
title: Comparisons
|
||||
description: How is Fumadocs different from other existing frameworks?
|
||||
icon: GitCompareArrows
|
||||
---
|
||||
|
||||
## Nextra
|
||||
|
||||
Fumadocs is highly inspired by Nextra. For example, the Routing Conventions. That is why
|
||||
`meta.json` also exists in Fumadocs.
|
||||
|
||||
Nextra is more opinionated than Fumadocs. Fumadocs is accelerated by App Router. As a result, It provides many server-side functions, and you have to
|
||||
configure things manually compared to simply editing a configuration file.
|
||||
|
||||
Fumadocs works great if you want more control over everything, such as
|
||||
adding it to an existing codebase or implementing advanced routing.
|
||||
|
||||
### Feature Table
|
||||
|
||||
| Feature | Fumadocs | Nextra |
|
||||
| ------------------- | ------------ | ------------------------- |
|
||||
| Static Generation | Yes | Yes |
|
||||
| Cached | Yes | Yes |
|
||||
| Light/Dark Mode | Yes | Yes |
|
||||
| Syntax Highlighting | Yes | Yes |
|
||||
| Table of Contents | Yes | Yes |
|
||||
| Full-text Search | Yes | Yes |
|
||||
| i18n | Yes | Yes |
|
||||
| Last Git Edit Time | Yes | Yes |
|
||||
| Page Icons | Yes | Yes, via `_meta.js` files |
|
||||
| RSC | Yes | Yes |
|
||||
| Remote Source | Yes | Yes |
|
||||
| SEO | Via Metadata | Yes |
|
||||
| Built-in Components | Yes | Yes |
|
||||
| RTL Layout | Yes | Yes |
|
||||
|
||||
### Additional Features
|
||||
|
||||
Features supported via 3rd party libraries like [TypeDoc](https://typedoc.org) will not be listed here.
|
||||
|
||||
| Feature | Fumadocs | Nextra |
|
||||
| -------------------------- | -------- | ------ |
|
||||
| OpenAPI Integration | Yes | No |
|
||||
| TypeScript Docs Generation | Yes | No |
|
||||
| TypeScript Twoslash | Yes | Yes |
|
||||
|
||||
## Mintlify
|
||||
|
||||
Mintlify is a documentation service, as compared to Fumadocs, it offers a free tier but isn't completely free and open source.
|
||||
|
||||
Fumadocs is not as powerful as Mintlify, for example, the OpenAPI integration of Mintlify.
|
||||
As the creator of Fumadocs, I wouldn't recommend switching to Fumadocs from Mintlify if you're satisfied with the current way you build docs.
|
||||
However, I believe Fumadocs is a suitable tool for all Next.js developers who want to have elegant docs.
|
||||
|
||||
## Docusaurus
|
||||
|
||||
Docusaurus is a powerful framework based on React.js. It offers many cool
|
||||
features with plugins and custom themes.
|
||||
|
||||
### Better DX
|
||||
|
||||
Since Fumadocs is built on the top of Next.js, you'll have to start the Next.js dev
|
||||
server every time to review changes, and initial boilerplate code is relatively more
|
||||
compared to Docusaurus.
|
||||
|
||||
For a simple docs, Docusaurus might be a better choice if you don't need any Next.js specific functionality.
|
||||
|
||||
However, when you want to use Next.js, or seek extra customizability like tuning default UI components, Fumadocs could be a better choice.
|
||||
|
||||
### Plugins
|
||||
|
||||
You can easily achieve many things with plugins, their ecosystem is indeed larger and maintained by many contributors.
|
||||
|
||||
In comparison, the flexibility of Fumadocs allows you to implement them on your own, it may take longer to tune it to your satisfaction.
|
68
content/docs/comparisons.zh.mdx
Normal file
68
content/docs/comparisons.zh.mdx
Normal file
@ -0,0 +1,68 @@
|
||||
---
|
||||
title: 对比
|
||||
description: Fumadocs 与其他现有框架有何不同?
|
||||
icon: GitCompareArrows
|
||||
---
|
||||
|
||||
## Nextra
|
||||
|
||||
Fumadocs 深受 Nextra 启发。例如,路由约定。这就是为什么 Fumadocs 中也存在 `meta.json`。
|
||||
|
||||
Nextra 比 Fumadocs 更加固执己见。Fumadocs 由 App Router 加速。因此,它提供了许多服务器端功能,与简单编辑配置文件相比,您必须手动配置一些内容。
|
||||
|
||||
如果您想要对一切都有更多的控制,比如将其添加到现有代码库或实现高级路由,Fumadocs 会表现得很出色。
|
||||
|
||||
### 功能表
|
||||
|
||||
| 功能 | Fumadocs | Nextra |
|
||||
| ------------------- | ------------ | ------------------------- |
|
||||
| 静态生成 | 是 | 是 |
|
||||
| 缓存 | 是 | 是 |
|
||||
| 明/暗模式 | 是 | 是 |
|
||||
| 语法高亮 | 是 | 是 |
|
||||
| 目录 | 是 | 是 |
|
||||
| 全文搜索 | 是 | 是 |
|
||||
| 国际化 | 是 | 是 |
|
||||
| 最后 Git 编辑时间 | 是 | 是 |
|
||||
| 页面图标 | 是 | 是,通过 `_meta.js` 文件 |
|
||||
| RSC | 是 | 是 |
|
||||
| 远程源 | 是 | 是 |
|
||||
| SEO | 通过元数据 | 是 |
|
||||
| 内置组件 | 是 | 是 |
|
||||
| RTL 布局 | 是 | 是 |
|
||||
|
||||
### 附加功能
|
||||
|
||||
通过第三方库支持的功能(如 [TypeDoc](https://typedoc.org))不会在此列出。
|
||||
|
||||
| 功能 | Fumadocs | Nextra |
|
||||
| -------------------------- | -------- | ------ |
|
||||
| OpenAPI 集成 | 是 | 否 |
|
||||
| TypeScript 文档生成 | 是 | 否 |
|
||||
| TypeScript Twoslash | 是 | 是 |
|
||||
|
||||
## Mintlify
|
||||
|
||||
Mintlify 是一项文档服务,与 Fumadocs 相比,它提供免费套餐,但并非完全免费和开源。
|
||||
|
||||
Fumadocs 不如 Mintlify 强大,例如 Mintlify 的 OpenAPI 集成。
|
||||
作为 Fumadocs 的创建者,如果您对当前构建文档的方式感到满意,我不建议从 Mintlify 切换到 Fumadocs。
|
||||
然而,我相信 Fumadocs 是所有想要拥有优雅文档的 Next.js 开发者的合适工具。
|
||||
|
||||
## Docusaurus
|
||||
|
||||
Docusaurus 是一个基于 React.js 的强大框架。它通过插件和自定义主题提供了许多酷炫的功能。
|
||||
|
||||
### 更好的开发者体验
|
||||
|
||||
由于 Fumadocs 构建在 Next.js 之上,您每次都必须启动 Next.js 开发服务器来查看更改,并且相对于 Docusaurus,初始样板代码较多。
|
||||
|
||||
对于简单的文档,如果您不需要任何特定于 Next.js 的功能,Docusaurus 可能是更好的选择。
|
||||
|
||||
然而,当您想要使用 Next.js,或寻求更多的可定制性,如调整默认 UI 组件时,Fumadocs 可能是更好的选择。
|
||||
|
||||
### 插件
|
||||
|
||||
您可以通过插件轻松实现许多功能,他们的生态系统确实更大,并由许多贡献者维护。
|
||||
|
||||
相比之下,Fumadocs 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。
|
43
content/docs/components/accordion.mdx
Normal file
43
content/docs/components/accordion.mdx
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Accordion
|
||||
description: Add Accordions to your documentation
|
||||
preview: accordion
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Based on
|
||||
[Radix UI Accordion](https://www.radix-ui.com/primitives/docs/components/accordion), useful for FAQ sections.
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
|
||||
<Accordions type="single">
|
||||
<Accordion title="My Title">My Content</Accordion>
|
||||
</Accordions>;
|
||||
```
|
||||
|
||||
### Accordions
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionsProps" /> */}
|
||||
|
||||
### Accordion
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionProps" /> */}
|
||||
|
||||
### Linking to Accordion
|
||||
|
||||
You can specify an `id` for accordion. The accordion will automatically open when the user is navigating to the page with the specified `id` in hash parameter.
|
||||
|
||||
```mdx
|
||||
<Accordions>
|
||||
<Accordion title="My Title" id="my-title">
|
||||
|
||||
My Content
|
||||
|
||||
</Accordion>
|
||||
</Accordions>
|
||||
```
|
||||
|
||||
> The value of accordion is same as title by default. When an id presents, it will be used as the value instead.
|
42
content/docs/components/accordion.zh.mdx
Normal file
42
content/docs/components/accordion.zh.mdx
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: 手风琴
|
||||
description: 在文档中添加手风琴组件
|
||||
preview: accordion
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
基于 [Radix UI Accordion](https://www.radix-ui.com/primitives/docs/components/accordion),对 FAQ 部分特别有用。
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
|
||||
<Accordions type="single">
|
||||
<Accordion title="我的标题">我的内容</Accordion>
|
||||
</Accordions>;
|
||||
```
|
||||
|
||||
### Accordions
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionsProps" /> */}
|
||||
|
||||
### Accordion
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionProps" /> */}
|
||||
|
||||
### 链接到手风琴
|
||||
|
||||
您可以为手风琴指定一个 `id`。当用户导航到带有指定 `id` 的哈希参数的页面时,手风琴将自动打开。
|
||||
|
||||
```mdx
|
||||
<Accordions>
|
||||
<Accordion title="我的标题" id="my-title">
|
||||
|
||||
我的内容
|
||||
|
||||
</Accordion>
|
||||
</Accordions>
|
||||
```
|
||||
|
||||
> 手风琴的值默认与标题相同。当存在 id 时,它将被用作值。
|
61
content/docs/components/banner.mdx
Normal file
61
content/docs/components/banner.mdx
Normal file
@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Banner
|
||||
description: Add a banner to your site
|
||||
preview: banner
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Put the element at the top of your root layout, you can use it for displaying announcements.
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}): React.ReactElement {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Banner>Hello World</Banner>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Variant
|
||||
|
||||
Change the default variant.
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner variant="rainbow">Hello World</Banner>;
|
||||
```
|
||||
|
||||
### Change Layout
|
||||
|
||||
By default, the banner uses a `style` tag to modify Fumadocs layouts (e.g. reduce the sidebar height).
|
||||
You can disable it with:
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner changeLayout={false}>Hello World</Banner>;
|
||||
```
|
||||
|
||||
### Close
|
||||
|
||||
To allow users to close the banner, give the banner an ID.
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner id="hello-world">Hello World</Banner>;
|
||||
```
|
||||
|
||||
The state will be automatically persisted.
|
61
content/docs/components/banner.zh.mdx
Normal file
61
content/docs/components/banner.zh.mdx
Normal file
@ -0,0 +1,61 @@
|
||||
---
|
||||
title: 横幅
|
||||
description: 在您的网站添加横幅
|
||||
preview: banner
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
将元素放在根布局的顶部,您可以用它来显示公告。
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}): React.ReactElement {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Banner>Hello World</Banner>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 变体
|
||||
|
||||
更改默认变体。
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner variant="rainbow">Hello World</Banner>;
|
||||
```
|
||||
|
||||
### 更改布局
|
||||
|
||||
默认情况下,横幅使用 `style` 标签来修改 Fumadocs 布局(例如减少侧边栏高度)。
|
||||
您可以通过以下方式禁用它:
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner changeLayout={false}>Hello World</Banner>;
|
||||
```
|
||||
|
||||
### 关闭
|
||||
|
||||
要允许用户关闭横幅,请给横幅一个 ID。
|
||||
|
||||
```tsx
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
|
||||
<Banner id="hello-world">Hello World</Banner>;
|
||||
```
|
||||
|
||||
状态将自动保持。
|
38
content/docs/components/dynamic-codeblock.mdx
Normal file
38
content/docs/components/dynamic-codeblock.mdx
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Code Block (Dynamic)
|
||||
description: A codeblock that also highlights code
|
||||
preview: dynamicCodeBlock
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
|
||||
|
||||
<DynamicCodeBlock lang="ts" code='console.log("Hello World")' />;
|
||||
```
|
||||
|
||||
This component, different from the MDX [`CodeBlock`](/docs/mdx/codeblock) component, can be used without MDX.
|
||||
It highlights the code with Shiki and use the default component to render it.
|
||||
|
||||
Features:
|
||||
|
||||
- Can be pre-rendered on server
|
||||
- load languages and themes on browser lazily
|
||||
|
||||
### Options
|
||||
|
||||
```tsx
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
|
||||
|
||||
<DynamicCodeBlock
|
||||
lang="ts"
|
||||
code='console.log("Hello World")'
|
||||
options={{
|
||||
components: {
|
||||
// add/override components
|
||||
},
|
||||
// or Shiki options
|
||||
}}
|
||||
/>;
|
||||
```
|
38
content/docs/components/dynamic-codeblock.zh.mdx
Normal file
38
content/docs/components/dynamic-codeblock.zh.mdx
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: 代码块(动态)
|
||||
description: 也能高亮代码的代码块
|
||||
preview: dynamicCodeBlock
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
```tsx
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
|
||||
|
||||
<DynamicCodeBlock lang="ts" code='console.log("Hello World")' />;
|
||||
```
|
||||
|
||||
这个组件与 MDX [`CodeBlock`](/docs/mdx/codeblock) 组件不同,可以在不使用 MDX 的情况下使用。
|
||||
它使用 Shiki 高亮代码,并使用默认组件渲染它。
|
||||
|
||||
特点:
|
||||
|
||||
- 可以在服务器上预渲染
|
||||
- 在浏览器上懒加载语言和主题
|
||||
|
||||
### 选项
|
||||
|
||||
```tsx
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
|
||||
|
||||
<DynamicCodeBlock
|
||||
lang="ts"
|
||||
code='console.log("Hello World")'
|
||||
options={{
|
||||
components: {
|
||||
// 添加/覆盖组件
|
||||
},
|
||||
// 或 Shiki 选项
|
||||
}}
|
||||
/>;
|
||||
```
|
35
content/docs/components/files.mdx
Normal file
35
content/docs/components/files.mdx
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: Files
|
||||
description: Display file structure in your documentation
|
||||
preview: 'files'
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Wrap file components in `Files`.
|
||||
|
||||
```mdx
|
||||
import { File, Folder, Files } from 'fumadocs-ui/components/files';
|
||||
|
||||
<Files>
|
||||
<Folder name="app" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
<File name="page.tsx" />
|
||||
<File name="global.css" />
|
||||
</Folder>
|
||||
<Folder name="components">
|
||||
<File name="button.tsx" />
|
||||
<File name="tabs.tsx" />
|
||||
<File name="dialog.tsx" />
|
||||
</Folder>
|
||||
<File name="package.json" />
|
||||
</Files>
|
||||
```
|
||||
|
||||
### File
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="FileProps" /> */}
|
||||
|
||||
### Folder
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="FolderProps" /> */}
|
35
content/docs/components/files.zh.mdx
Normal file
35
content/docs/components/files.zh.mdx
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: 文件
|
||||
description: 在文档中显示文件结构
|
||||
preview: 'files'
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
将文件组件包装在 `Files` 中。
|
||||
|
||||
```mdx
|
||||
import { File, Folder, Files } from 'fumadocs-ui/components/files';
|
||||
|
||||
<Files>
|
||||
<Folder name="app" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
<File name="page.tsx" />
|
||||
<File name="global.css" />
|
||||
</Folder>
|
||||
<Folder name="components">
|
||||
<File name="button.tsx" />
|
||||
<File name="tabs.tsx" />
|
||||
<File name="dialog.tsx" />
|
||||
</Folder>
|
||||
<File name="package.json" />
|
||||
</Files>
|
||||
```
|
||||
|
||||
### File
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="FileProps" /> */}
|
||||
|
||||
### Folder
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="FolderProps" /> */}
|
45
content/docs/components/github-info.mdx
Normal file
45
content/docs/components/github-info.mdx
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: GitHub Info
|
||||
description: Display your GitHub repository information
|
||||
preview: githubInfo
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
|
||||
<GithubInfo
|
||||
owner="fuma-nama"
|
||||
repo="fumadocs"
|
||||
// your own GitHub access token (optional)
|
||||
token={process.env.GITHUB_TOKEN}
|
||||
/>;
|
||||
```
|
||||
|
||||
It's recommended to add it to your docs layout with `links` option:
|
||||
|
||||
```tsx title="app/docs/layout.tsx"
|
||||
import { DocsLayout, type DocsLayoutProps } from 'fumadocs-ui/layouts/notebook';
|
||||
import type { ReactNode } from 'react';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
import { source } from '@/lib/source';
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
|
||||
const docsOptions: DocsLayoutProps = {
|
||||
...baseOptions,
|
||||
tree: source.pageTree,
|
||||
links: [
|
||||
{
|
||||
type: 'custom',
|
||||
children: (
|
||||
<GithubInfo owner="fuma-nama" repo="fumadocs" className="lg:-mx-2" />
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return <DocsLayout {...docsOptions}>{children}</DocsLayout>;
|
||||
}
|
||||
```
|
45
content/docs/components/github-info.zh.mdx
Normal file
45
content/docs/components/github-info.zh.mdx
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: GitHub 信息
|
||||
description: 显示您的 GitHub 仓库信息
|
||||
preview: githubInfo
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
```tsx
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
|
||||
<GithubInfo
|
||||
owner="fuma-nama"
|
||||
repo="fumadocs"
|
||||
// 您自己的 GitHub 访问令牌(可选)
|
||||
token={process.env.GITHUB_TOKEN}
|
||||
/>;
|
||||
```
|
||||
|
||||
建议将其添加到您的文档布局中,使用 `links` 选项:
|
||||
|
||||
```tsx title="app/docs/layout.tsx"
|
||||
import { DocsLayout, type DocsLayoutProps } from 'fumadocs-ui/layouts/notebook';
|
||||
import type { ReactNode } from 'react';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
import { source } from '@/lib/source';
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
|
||||
const docsOptions: DocsLayoutProps = {
|
||||
...baseOptions,
|
||||
tree: source.pageTree,
|
||||
links: [
|
||||
{
|
||||
type: 'custom',
|
||||
children: (
|
||||
<GithubInfo owner="fuma-nama" repo="fumadocs" className="lg:-mx-2" />
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return <DocsLayout {...docsOptions}>{children}</DocsLayout>;
|
||||
}
|
||||
```
|
34
content/docs/components/image-zoom.mdx
Normal file
34
content/docs/components/image-zoom.mdx
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Zoomable Image
|
||||
description: Allow zoom-in images in your documentation
|
||||
preview: zoomImage
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Replace `img` with `ImageZoom` in your MDX components.
|
||||
|
||||
```tsx title="app/docs/[[...slug]]/page.tsx"
|
||||
import { ImageZoom } from 'fumadocs-ui/components/image-zoom';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
|
||||
return (
|
||||
<MdxContent
|
||||
components={{
|
||||
...defaultMdxComponents,
|
||||
img: (props) => <ImageZoom {...(props as any)} />,
|
||||
// other Mdx components
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
Now image zoom will be automatically enabled on all images.
|
||||
|
||||
```mdx
|
||||

|
||||
```
|
||||
|
||||
### Image Optimization
|
||||
|
||||
A default [`sizes` property](https://nextjs.org/docs/app/api-reference/components/image#sizes) will be defined for Next.js `<Image />` component if not specified.
|
34
content/docs/components/image-zoom.zh.mdx
Normal file
34
content/docs/components/image-zoom.zh.mdx
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: 可缩放图片
|
||||
description: 在文档中允许放大图片
|
||||
preview: zoomImage
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
在 MDX 组件中用 `ImageZoom` 替换 `img`。
|
||||
|
||||
```tsx title="app/docs/[[...slug]]/page.tsx"
|
||||
import { ImageZoom } from 'fumadocs-ui/components/image-zoom';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
|
||||
return (
|
||||
<MdxContent
|
||||
components={{
|
||||
...defaultMdxComponents,
|
||||
img: (props) => <ImageZoom {...(props as any)} />,
|
||||
// 其他 Mdx 组件
|
||||
}}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
现在,所有图片都将自动启用图片缩放功能。
|
||||
|
||||
```mdx
|
||||

|
||||
```
|
||||
|
||||
### 图片优化
|
||||
|
||||
如果未指定,将为 Next.js `<Image />` 组件定义默认的 [`sizes` 属性](https://nextjs.org/docs/app/api-reference/components/image#sizes)。
|
5
content/docs/components/index.mdx
Normal file
5
content/docs/components/index.mdx
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Components
|
||||
description: Additional components to improve your docs
|
||||
index: true
|
||||
---
|
5
content/docs/components/index.zh.mdx
Normal file
5
content/docs/components/index.zh.mdx
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 组件
|
||||
description: 改进文档的额外组件
|
||||
index: true
|
||||
---
|
31
content/docs/components/inline-toc.mdx
Normal file
31
content/docs/components/inline-toc.mdx
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Inline TOC
|
||||
description: Add Inline TOC into your documentation
|
||||
preview: inlineTOC
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Pass TOC items to the component.
|
||||
|
||||
```mdx
|
||||
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
|
||||
|
||||
<InlineTOC items={toc} />
|
||||
```
|
||||
|
||||
### Use in Pages
|
||||
|
||||
You can add inline TOC into every page.
|
||||
|
||||
```tsx
|
||||
<DocsPage>
|
||||
...
|
||||
<InlineTOC items={toc} />
|
||||
...
|
||||
</DocsPage>
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="InlineTOCProps" /> */}
|
31
content/docs/components/inline-toc.zh.mdx
Normal file
31
content/docs/components/inline-toc.zh.mdx
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: 内联目录
|
||||
description: 在文档中添加内联目录
|
||||
preview: inlineTOC
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
将 TOC 项目传递给组件。
|
||||
|
||||
```mdx
|
||||
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
|
||||
|
||||
<InlineTOC items={toc} />
|
||||
```
|
||||
|
||||
### 在页面中使用
|
||||
|
||||
您可以在每个页面中添加内联目录。
|
||||
|
||||
```tsx
|
||||
<DocsPage>
|
||||
...
|
||||
<InlineTOC items={toc} />
|
||||
...
|
||||
</DocsPage>
|
||||
```
|
||||
|
||||
## 参考
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="InlineTOCProps" /> */}
|
35
content/docs/components/root-toggle.mdx
Normal file
35
content/docs/components/root-toggle.mdx
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: Root Toggle
|
||||
description: Switch between page trees
|
||||
preview: rootToggle
|
||||
---
|
||||
|
||||
## Usages
|
||||
|
||||
Add this component to your sidebar or other places you want.
|
||||
|
||||
```tsx
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { RootToggle } from 'fumadocs-ui/components/layout/root-toggle';
|
||||
|
||||
<DocsLayout
|
||||
sidebar={{
|
||||
banner: (
|
||||
<RootToggle
|
||||
options={[
|
||||
{
|
||||
title: 'Folder 1',
|
||||
description: 'Pages in folder 1',
|
||||
url: '/path/to/page-tree-1',
|
||||
},
|
||||
{
|
||||
title: 'Folder 2',
|
||||
description: 'Pages in folder 2',
|
||||
url: '/path/to/page-tree-2',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
```
|
35
content/docs/components/root-toggle.zh.mdx
Normal file
35
content/docs/components/root-toggle.zh.mdx
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: 根切换器
|
||||
description: 在页面树之间切换
|
||||
preview: rootToggle
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
将此组件添加到您的侧边栏或您想要的其他地方。
|
||||
|
||||
```tsx
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { RootToggle } from 'fumadocs-ui/components/layout/root-toggle';
|
||||
|
||||
<DocsLayout
|
||||
sidebar={{
|
||||
banner: (
|
||||
<RootToggle
|
||||
options={[
|
||||
{
|
||||
title: '文件夹 1',
|
||||
description: '文件夹 1 中的页面',
|
||||
url: '/path/to/page-tree-1',
|
||||
},
|
||||
{
|
||||
title: '文件夹 2',
|
||||
description: '文件夹 2 中的页面',
|
||||
url: '/path/to/page-tree-2',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
```
|
57
content/docs/components/steps.mdx
Normal file
57
content/docs/components/steps.mdx
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Steps
|
||||
description: Adding steps to your docs
|
||||
preview: steps
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Put your steps into the `Steps` container.
|
||||
|
||||
```mdx
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
|
||||
### Hello World
|
||||
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
|
||||
### Hello World
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
```
|
||||
|
||||
> We recommend using Tailwind CSS utility classes directly on Tailwind CSS projects.
|
||||
|
||||
### Without imports
|
||||
|
||||
You can use the Tailwind CSS utilities without importing it.
|
||||
|
||||
```mdx
|
||||
<div className="fd-steps">
|
||||
<div className="fd-step" />
|
||||
</div>
|
||||
```
|
||||
|
||||
It supports adding step styles to only headings with arbitrary variants.
|
||||
|
||||
```mdx
|
||||
<div className='fd-steps [&_h3]:fd-step'>
|
||||
|
||||
### Hello World
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
<div className='fd-steps [&_h3]:fd-step'>
|
||||
|
||||
### Hello World
|
||||
|
||||
You no longer need to use the step component anymore.
|
||||
|
||||
</div>
|
57
content/docs/components/steps.zh.mdx
Normal file
57
content/docs/components/steps.zh.mdx
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: 步骤
|
||||
description: 在文档中添加步骤
|
||||
preview: steps
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
将您的步骤放入 `Steps` 容器中。
|
||||
|
||||
```mdx
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
|
||||
### 你好世界
|
||||
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
|
||||
### 你好世界
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
```
|
||||
|
||||
> 我们建议在 Tailwind CSS 项目中直接使用 Tailwind CSS 实用类。
|
||||
|
||||
### 不使用导入
|
||||
|
||||
您可以在不导入的情况下使用 Tailwind CSS 实用工具。
|
||||
|
||||
```mdx
|
||||
<div className="fd-steps">
|
||||
<div className="fd-step" />
|
||||
</div>
|
||||
```
|
||||
|
||||
它支持仅对带有任意变体的标题添加步骤样式。
|
||||
|
||||
```mdx
|
||||
<div className='fd-steps [&_h3]:fd-step'>
|
||||
|
||||
### 你好世界
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
<div className='fd-steps [&_h3]:fd-step'>
|
||||
|
||||
### 你好世界
|
||||
|
||||
您不再需要使用步骤组件了。
|
||||
|
||||
</div>
|
146
content/docs/components/tabs.mdx
Normal file
146
content/docs/components/tabs.mdx
Normal file
@ -0,0 +1,146 @@
|
||||
---
|
||||
title: Tabs
|
||||
description:
|
||||
A Tabs component built with Radix UI, with additional features such as
|
||||
persistent and shared value.
|
||||
preview: tabs
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Import it in your MDX documents.
|
||||
|
||||
```mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Without `value`
|
||||
|
||||
Without a `value`, it detects from the children index. Note that it might cause errors on re-renders, it's not encouraged if the tabs might change.
|
||||
|
||||
```mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}>
|
||||
<Tab>Javascript is weird</Tab>
|
||||
<Tab>Rust is fast</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
#### Demo with Re-renders
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}>
|
||||
<Tab>Javascript is weird</Tab>
|
||||
<Tab>Rust is fast</Tab>
|
||||
</Tabs>
|
||||
|
||||
{/* <WithoutValueTest /> */}
|
||||
|
||||
### Shared Value
|
||||
|
||||
By passing an `groupId` property, you can share a value across all tabs with the same
|
||||
id.
|
||||
|
||||
```mdx
|
||||
<Tabs groupId="language" items={['Javascript', 'Rust']}>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Persistent
|
||||
|
||||
You can enable persistent by passing a `persist` property. The value will be
|
||||
stored in `localStorage`, with its id as the key.
|
||||
|
||||
```mdx
|
||||
<Tabs groupId="language" items={['Javascript', 'Rust']} persist>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
> Persistent only works if you have passed an `id`.
|
||||
|
||||
### Default Value
|
||||
|
||||
Set a default value by passing `defaultIndex`.
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust']} defaultIndex={1}>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Link to Tab
|
||||
|
||||
Use HTML `id` attribute to link to a specific tab.
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust', 'C++']}>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
<Tab id="tab-cpp" value="C++">
|
||||
`Hello World`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
You can add the hash `#tab-cpp` to your URL and reload, the C++ tab will be activated.
|
||||
|
||||
<Tabs items={['Javascript', 'Rust', 'C++']}>
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
<Tab id="tab-cpp" value="C++">
|
||||
`Hello World`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Additionally, the `updateAnchor` property can be set to `true` in the `Tabs` component
|
||||
to automatically update the URL hash whenever time a new tab is selected:
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust', 'C++']} updateAnchor>
|
||||
<Tab id="tab-js" value="Javascript">
|
||||
Javascript is weird
|
||||
</Tab>
|
||||
<Tab id="tab-rs" value="Rust">
|
||||
Rust is fast
|
||||
</Tab>
|
||||
<Tab id="tab-cpp" value="C++">
|
||||
`Hello World`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
{/* <UrlBar /> */}
|
||||
|
||||
<Tabs items={['Hello', 'World']} updateAnchor>
|
||||
<Tab id="tab-hello" value="Hello">
|
||||
Hello!
|
||||
</Tab>
|
||||
<Tab id="tab-world" value="World">
|
||||
World!
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Advanced
|
||||
|
||||
You can use the styled Radix UI primitive directly from exported `Primitive`.
|
||||
|
||||
```mdx
|
||||
import { Primitive } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Primitive.Tabs>
|
||||
<Primitive.TabsList>
|
||||
<Primitive.TabsTrigger />
|
||||
</Primitive.TabsList>
|
||||
<Primitive.TabsContent />
|
||||
</Primitive.Tabs>
|
||||
```
|
114
content/docs/components/tabs.zh.mdx
Normal file
114
content/docs/components/tabs.zh.mdx
Normal file
@ -0,0 +1,114 @@
|
||||
---
|
||||
title: 选项卡
|
||||
description:
|
||||
使用 Radix UI 构建的选项卡组件,具有持久性和共享值等附加功能。
|
||||
preview: tabs
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
在 MDX 文档中导入它。
|
||||
|
||||
```mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}>
|
||||
<Tab value="Javascript">Javascript 很奇怪</Tab>
|
||||
<Tab value="Rust">Rust 很快</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### 不使用 `value`
|
||||
|
||||
如果没有 `value`,它会从子元素索引中检测。请注意,这可能会在重新渲染时导致错误,如果选项卡可能会改变,不建议这样做。
|
||||
|
||||
```mdx
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}>
|
||||
<Tab>Javascript 很奇怪</Tab>
|
||||
<Tab>Rust 很快</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### 共享值
|
||||
|
||||
通过传递 `groupId` 属性,您可以在具有相同 ID 的所有选项卡之间共享值。
|
||||
|
||||
```mdx
|
||||
<Tabs groupId="language" items={['Javascript', 'Rust']}>
|
||||
<Tab value="Javascript">Javascript 很奇怪</Tab>
|
||||
<Tab value="Rust">Rust 很快</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### 持久性
|
||||
|
||||
您可以通过传递 `persist` 属性启用持久性。该值将存储在 `localStorage` 中,以其 ID 作为键。
|
||||
|
||||
```mdx
|
||||
<Tabs groupId="language" items={['Javascript', 'Rust']} persist>
|
||||
<Tab value="Javascript">Javascript 很奇怪</Tab>
|
||||
<Tab value="Rust">Rust 很快</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
> 持久性仅在您传递了 `id` 时有效。
|
||||
|
||||
### 默认值
|
||||
|
||||
通过传递 `defaultIndex` 设置默认值。
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust']} defaultIndex={1}>
|
||||
<Tab value="Javascript">Javascript 很奇怪</Tab>
|
||||
<Tab value="Rust">Rust 很快</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### 链接到选项卡
|
||||
|
||||
使用 HTML `id` 属性链接到特定选项卡。
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust', 'C++']}>
|
||||
<Tab value="Javascript">Javascript 很奇怪</Tab>
|
||||
<Tab value="Rust">Rust 很快</Tab>
|
||||
<Tab id="tab-cpp" value="C++">
|
||||
`Hello World`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
您可以在 URL 中添加哈希 `#tab-cpp` 并重新加载,C++ 选项卡将被激活。
|
||||
|
||||
此外,可以在 `Tabs` 组件中将 `updateAnchor` 属性设置为 `true`,以便在每次选择新选项卡时自动更新 URL 哈希:
|
||||
|
||||
```mdx
|
||||
<Tabs items={['Javascript', 'Rust', 'C++']} updateAnchor>
|
||||
<Tab id="tab-js" value="Javascript">
|
||||
Javascript 很奇怪
|
||||
</Tab>
|
||||
<Tab id="tab-rs" value="Rust">
|
||||
Rust 很快
|
||||
</Tab>
|
||||
<Tab id="tab-cpp" value="C++">
|
||||
`Hello World`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### 高级用法
|
||||
|
||||
您可以直接从导出的 `Primitive` 中使用样式化的 Radix UI 原语。
|
||||
|
||||
```mdx
|
||||
import { Primitive } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<Primitive.Tabs>
|
||||
<Primitive.TabsList>
|
||||
<Primitive.TabsTrigger />
|
||||
</Primitive.TabsList>
|
||||
<Primitive.TabsContent />
|
||||
</Primitive.Tabs>
|
||||
```
|
34
content/docs/components/type-table.mdx
Normal file
34
content/docs/components/type-table.mdx
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Type Table
|
||||
description: A table for documenting types
|
||||
preview: typeTable
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
It accepts a `type` property.
|
||||
|
||||
```mdx
|
||||
import { TypeTable } from 'fumadocs-ui/components/type-table';
|
||||
|
||||
<TypeTable
|
||||
type={{
|
||||
percentage: {
|
||||
description:
|
||||
'The percentage of scroll position to display the roll button',
|
||||
type: 'number',
|
||||
default: 0.2,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
### Type Table
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="TypeTableProps" /> */}
|
||||
|
||||
### Object Type
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="ObjectTypeProps" /> */}
|
34
content/docs/components/type-table.zh.mdx
Normal file
34
content/docs/components/type-table.zh.mdx
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: 类型表格
|
||||
description: 用于记录类型的表格
|
||||
preview: typeTable
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
它接受一个 `type` 属性。
|
||||
|
||||
```mdx
|
||||
import { TypeTable } from 'fumadocs-ui/components/type-table';
|
||||
|
||||
<TypeTable
|
||||
type={{
|
||||
percentage: {
|
||||
description:
|
||||
'显示滚动按钮的滚动位置百分比',
|
||||
type: 'number',
|
||||
default: 0.2,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## 参考
|
||||
|
||||
### Type Table
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="TypeTableProps" /> */}
|
||||
|
||||
### Object Type
|
||||
|
||||
{/* <AutoTypeTable path="./content/docs/props.ts" name="ObjectTypeProps" /> */}
|
51
content/docs/customisation.mdx
Normal file
51
content/docs/customisation.mdx
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Overview
|
||||
description: An overview of Fumadocs UI
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Page Tree
|
||||
|
||||
Navigation elements like sidebar take a [Page Tree](/docs/headless/page-tree) to render navigation links, it's a tree that describes all available pages and folders.
|
||||
|
||||
Normally, it is generated from your file structure using [`loader()`](/docs/headless/source-api), you can learn [how to organize pages](/docs/page-conventions).
|
||||
|
||||
## Customisation
|
||||
|
||||
### Layouts
|
||||
|
||||
You can use the exposed options of different layouts:
|
||||
|
||||
<Cards>
|
||||
<Card title="Docs Layout" href="/docs/layouts/docs">
|
||||
Layout for docs
|
||||
</Card>
|
||||
<Card title="Docs Page" href="/docs/layouts/page">
|
||||
Layout for docs content
|
||||
</Card>
|
||||
<Card title="Notebook Layout" href="/docs/layouts/notebook">
|
||||
A more compact version of Docs Layout
|
||||
</Card>
|
||||
<Card title="Home Layout" href="/docs/layouts/home-layout">
|
||||
Layout for other pages
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Components
|
||||
|
||||
Fumadocs UI also offers styled components for interactive examples to enhance your docs, you can customise them with exposed props like `style` and `className`.
|
||||
|
||||
See [Components](/docs/components).
|
||||
|
||||
### Design System
|
||||
|
||||
Since the design system is built on Tailwind CSS, you can customise it [with CSS Variables](/docs/theme#colors).
|
||||
|
||||
### CLI
|
||||
|
||||
If none of them suits you, Fumadocs CLI is a tool to install Fumadocs UI components and layouts to your codebase, similar to Shadcn UI. Allowing you to fully customise Fumadocs UI:
|
||||
|
||||
```mdx
|
||||
npx fumadocs add
|
||||
```
|
51
content/docs/customisation.zh.mdx
Normal file
51
content/docs/customisation.zh.mdx
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: 概览
|
||||
description: Fumadocs UI 的概览
|
||||
---
|
||||
|
||||
## 架构
|
||||
|
||||
### 页面树
|
||||
|
||||
侧边栏等导航元素使用[页面树](/docs/headless/page-tree)来渲染导航链接,它是描述所有可用页面和文件夹的树形结构。
|
||||
|
||||
通常,它是使用 [`loader()`](/docs/headless/source-api) 从您的文件结构生成的,您可以了解[如何组织页面](/docs/page-conventions)。
|
||||
|
||||
## 自定义
|
||||
|
||||
### 布局
|
||||
|
||||
您可以使用不同布局的暴露选项:
|
||||
|
||||
<Cards>
|
||||
<Card title="文档布局" href="/docs/layouts/docs">
|
||||
文档的布局
|
||||
</Card>
|
||||
<Card title="文档页面" href="/docs/layouts/page">
|
||||
文档内容的布局
|
||||
</Card>
|
||||
<Card title="笔记本布局" href="/docs/layouts/notebook">
|
||||
文档布局的更紧凑版本
|
||||
</Card>
|
||||
<Card title="主页布局" href="/docs/layouts/home-layout">
|
||||
其他页面的布局
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### 组件
|
||||
|
||||
Fumadocs UI 还提供了样式化组件,用于交互式示例以增强您的文档,您可以使用暴露的道具如 `style` 和 `className` 来自定义它们。
|
||||
|
||||
参见[组件](/docs/components)。
|
||||
|
||||
### 设计系统
|
||||
|
||||
由于设计系统是基于 Tailwind CSS 构建的,您可以[通过 CSS 变量](/docs/theme#colors)自定义它。
|
||||
|
||||
### CLI
|
||||
|
||||
如果这些都不适合您,Fumadocs CLI 是一个工具,可以将 Fumadocs UI 组件和布局安装到您的代码库中,类似于 Shadcn UI。允许您完全自定义 Fumadocs UI:
|
||||
|
||||
```mdx
|
||||
npx fumadocs add
|
||||
```
|
278
content/docs/index.mdx
Normal file
278
content/docs/index.mdx
Normal file
@ -0,0 +1,278 @@
|
||||
---
|
||||
title: Quick Start
|
||||
description: Getting Started with Fumadocs
|
||||
icon: Album
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> is a **documentation framework** based on Next.js, designed to be fast, flexible,
|
||||
and composes seamlessly into Next.js App Router.
|
||||
|
||||
Fumadocs has different parts:
|
||||
|
||||
<Cards>
|
||||
|
||||
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
|
||||
|
||||
Handles most of the logic, including document search, content source adapters, and Markdown extensions.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
|
||||
|
||||
The default theme of Fumadocs offers a beautiful look for documentation sites and interactive components.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Database />} title='Content Source'>
|
||||
|
||||
The source of your content, can be a CMS or local data layers like [Content Collections](https://www.content-collections.dev) and [Fumadocs MDX](/docs/mdx), the official content source.
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Terminal />} title='Fumadocs CLI'>
|
||||
|
||||
A command line tool to install UI components and automate things, useful for customizing layouts.
|
||||
|
||||
</Card>
|
||||
|
||||
</Cards>
|
||||
|
||||
<Callout title="Want to learn more?">
|
||||
Read our in-depth [What is Fumadocs](/docs/what-is-fumadocs) introduction.
|
||||
</Callout>
|
||||
|
||||
### Terminology
|
||||
|
||||
**Markdown/MDX:** Markdown is a markup language for creating formatted text. Fumadocs supports Markdown and MDX (superset of Markdown) out-of-the-box.
|
||||
|
||||
Although not required, some basic knowledge of Next.js App Router would be useful for further customisations.
|
||||
|
||||
## Automatic Installation
|
||||
|
||||
A minimum version of Node.js 18 required, note that Node.js 23.1 might have problems with Next.js production build.
|
||||
|
||||
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
|
||||
|
||||
```bash tab="npm"
|
||||
npm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="pnpm"
|
||||
pnpm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="yarn"
|
||||
yarn create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="bun"
|
||||
bun create fumadocs-app
|
||||
```
|
||||
|
||||
</Tabs>
|
||||
|
||||
It will ask you the framework and content source to use, a new fumadocs app should be initialized. Now you can start hacking!
|
||||
|
||||
<Callout title='From Existing Codebase?'>
|
||||
|
||||
You can follow the [Manual Installation](/docs/manual-installation) guide to get started.
|
||||
|
||||
</Callout>
|
||||
|
||||
### Enjoy!
|
||||
|
||||
Create your first MDX file in the docs folder.
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Yo what's up
|
||||
```
|
||||
|
||||
Run the app in development mode and see http://localhost:3000/docs.
|
||||
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Explore
|
||||
|
||||
In the project, you can see:
|
||||
|
||||
- `lib/source.ts`: Code for content source adapter, [`loader()`](/docs/headless/source-api) provides an interface to interact with your content source, and assigns URL to your pages.
|
||||
- `app/layout.config.tsx`: Shared options for layouts, optional but preferred to keep.
|
||||
|
||||
| Route | Description |
|
||||
| ------------------------- | ------------------------------------------------------ |
|
||||
| `app/(home)` | The route group for your landing page and other pages. |
|
||||
| `app/docs` | The documentation layout and pages. |
|
||||
| `app/api/search/route.ts` | The Route Handler for search. |
|
||||
|
||||
### Writing Content
|
||||
|
||||
For authoring docs, make sure to read:
|
||||
|
||||
<Cards>
|
||||
<Card href="/docs/markdown" title="Markdown">
|
||||
Fumadocs has some additional features for authoring content too.
|
||||
</Card>
|
||||
<Card href="/docs/navigation" title="Navigation">
|
||||
Learn how to customise navigation links/sidebar items.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Content Source
|
||||
|
||||
Content source handles all your content, like compiling Markdown files and validating frontmatter.
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
|
||||
Read the [Introduction](/docs/mdx) to learn how it handles your content.
|
||||
|
||||
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Custom Source'>
|
||||
|
||||
Fumadocs is not Markdown-exclusive. For other sources like Sanity, you can build a [custom content source](/docs/headless/custom-source).
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### Customise UI
|
||||
|
||||
See [Customisation Guide](/docs/customisation).
|
||||
|
||||
## FAQ
|
||||
|
||||
Some common questions you may encounter.
|
||||
|
||||
<Accordions>
|
||||
<Accordion id='fix-monorepo-styling' title="How to fix stylings not being applied in Monorepo?">
|
||||
|
||||
Sometimes, `fumadocs-ui` is not installed in the workspace of your Tailwind CSS configuration file. (e.g. a monorepo setup).
|
||||
|
||||
You have to ensure the `fumadocs-ui` package is scanned by Tailwind CSS, and give a correct relative path to `@source`.
|
||||
|
||||
For example, add `../../` to point to the `node_modules` folder in root workspace.
|
||||
|
||||
```css
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* [!code --] */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
/* [!code ++] */
|
||||
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='change-base-url' title="How to change the base route of /docs?">
|
||||
|
||||
You can change the base route of docs (e.g. from `/docs/page` to `/info/page`).
|
||||
Since Fumadocs uses Next.js App Router, you can simply rename the route:
|
||||
|
||||
<Files>
|
||||
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
<Folder name="app/info" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
And tell Fumadocs to use the new route in `source.ts`:
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: '/info',
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='dynamic-route' title="It uses Dynamic Route, will it be poor in performance?">
|
||||
|
||||
Next.js turns dynamic route into static routes when `generateStaticParams` is configured.
|
||||
Hence, it is as fast as static pages.
|
||||
|
||||
You can enable Static Exports on Next.js to get a static build output. (Notice that Route Handler doesn't work with static export, you have to configure static search)
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='custom-layout-docs-page' title='How to create a page in /docs without docs layout?'>
|
||||
|
||||
Same as managing layouts in Next.js App Router, remove the original MDX file from content directory (`/content/docs`).
|
||||
This ensures duplicated pages will not cause errors.
|
||||
|
||||
Now, You can add the page to another route group, which isn't a descendant of docs layout.
|
||||
|
||||
For example, under your `app` folder:
|
||||
|
||||
<Files>
|
||||
<File name="(home)/docs/page.tsx" />
|
||||
<Folder name="docs">
|
||||
<File name="layout.tsx" />
|
||||
<File name="[[...slug]]/page.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
will replace the `/docs` page with your `page.tsx`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-versions' title="How to implement docs with multi-version?">
|
||||
Use a separate deployment for each version.
|
||||
|
||||
On Vercel, this can be done by creating another branch for a specific version on your GitHub repository.
|
||||
To link to the sites of other versions, use the Links API or a custom navigation component.
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-docs' title="How to implement multi-docs?">
|
||||
We recommend to use [Sidebar Tabs](/docs/navigation/sidebar#sidebar-tabs).
|
||||
</Accordion>
|
||||
|
||||
</Accordions>
|
||||
|
||||
## Video Tutorials
|
||||
|
||||
<YoutubeVideo url="https://www.youtube.com/embed/BPnK-YbISHQ?si=TH_tI3e4MCgMHzGr" />
|
||||
|
||||
## Learn More
|
||||
|
||||
New to here? Don't worry, we are welcome for your questions.
|
||||
|
||||
If you find anything confusing, please give your feedback on [Github Discussion](https://github.com/fuma-nama/fumadocs/discussions)!
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="/docs/static-export"
|
||||
title="Configure Static Export"
|
||||
description="Learn how to enable static export on your docs"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/search"
|
||||
title="Customise Search"
|
||||
description="Learn how to customise document search"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/theme"
|
||||
title="Theming"
|
||||
description="Add themes to Fumadocs UI"
|
||||
/>
|
||||
<Card
|
||||
href="/docs/components"
|
||||
title="Components"
|
||||
description="See all available components to enhance your docs"
|
||||
/>
|
||||
</Cards>
|
253
content/docs/index.zh.mdx
Normal file
253
content/docs/index.zh.mdx
Normal file
@ -0,0 +1,253 @@
|
||||
---
|
||||
title: 快速入门
|
||||
description: Fumadocs 入门指南
|
||||
icon: Album
|
||||
---
|
||||
|
||||
## 简介
|
||||
|
||||
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> 是一个基于 Next.js 的**文档框架**,设计为快速、灵活,
|
||||
并无缝集成到 Next.js App Router 中。
|
||||
|
||||
Fumadocs 由不同部分组成:
|
||||
|
||||
<Cards>
|
||||
|
||||
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
|
||||
|
||||
处理大部分逻辑,包括文档搜索、内容源适配器和 Markdown 扩展。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
|
||||
|
||||
Fumadocs 的默认主题为文档站点提供了美观的外观和交互式组件。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Database />} title='Content Source'>
|
||||
|
||||
您内容的来源,可以是 CMS 或本地数据层,如 [Content Collections](https://www.content-collections.dev) 和 [Fumadocs MDX](/docs/mdx),即官方内容源。
|
||||
|
||||
</Card>
|
||||
|
||||
<Card icon={<Terminal />} title='Fumadocs CLI'>
|
||||
|
||||
一个命令行工具,用于安装 UI 组件和自动化操作,对于自定义布局非常有用。
|
||||
|
||||
</Card>
|
||||
|
||||
</Cards>
|
||||
|
||||
<Callout title="想了解更多?">
|
||||
阅读我们深入的 [什么是 Fumadocs](/docs/what-is-fumadocs) 介绍。
|
||||
</Callout>
|
||||
|
||||
### 术语
|
||||
|
||||
**Markdown/MDX:** Markdown 是一种用于创建格式化文本的标记语言。Fumadocs 默认支持 Markdown 和 MDX(Markdown 的超集)。
|
||||
|
||||
虽然不是必需的,但对 Next.js App Router 的基本了解对于进一步的自定义会很有帮助。
|
||||
|
||||
## 自动安装
|
||||
|
||||
需要 Node.js 18 或更高版本,请注意 Node.js 23.1 可能在 Next.js 生产构建中存在问题。
|
||||
|
||||
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
|
||||
|
||||
```bash tab="npm"
|
||||
npm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="pnpm"
|
||||
pnpm create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="yarn"
|
||||
yarn create fumadocs-app
|
||||
```
|
||||
|
||||
```bash tab="bun"
|
||||
bun create fumadocs-app
|
||||
```
|
||||
|
||||
</Tabs>
|
||||
|
||||
它会询问您要使用的框架和内容源,随后将初始化一个新的 fumadocs 应用程序。现在您可以开始动手了!
|
||||
|
||||
<Callout title='从现有代码库开始?'>
|
||||
|
||||
您可以按照 [手动安装](/docs/manual-installation) 指南开始。
|
||||
|
||||
</Callout>
|
||||
|
||||
### 尽情使用!
|
||||
|
||||
在 docs 文件夹中创建您的第一个 MDX 文件。
|
||||
|
||||
```mdx title="content/docs/index.mdx"
|
||||
---
|
||||
title: Hello World
|
||||
---
|
||||
|
||||
## Yo what's up
|
||||
```
|
||||
|
||||
在开发模式下运行应用程序并查看 http://localhost:3000/docs。
|
||||
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 探索
|
||||
|
||||
在项目中,您可以看到:
|
||||
|
||||
- `lib/source.ts`:内容源适配器的代码,[`loader()`](/docs/headless/source-api) 提供了与内容源交互的接口,并为您的页面分配 URL。
|
||||
- `app/layout.config.tsx`:布局的共享选项,可选但建议保留。
|
||||
|
||||
| 路由 | 描述 |
|
||||
| ------------------------- | -------------------------------------- |
|
||||
| `app/(home)` | 您的登陆页面和其他页面的路由组。 |
|
||||
| `app/docs` | 文档布局和页面。 |
|
||||
| `app/api/search/route.ts` | 搜索的路由处理器。 |
|
||||
|
||||
### 编写内容
|
||||
|
||||
对于编写文档,请务必阅读:
|
||||
|
||||
<Cards>
|
||||
<Card href="/docs/markdown" title="Markdown">
|
||||
Fumadocs 还有一些额外的内容创作功能。
|
||||
</Card>
|
||||
<Card href="/docs/navigation" title="Navigation">
|
||||
了解如何自定义导航链接/侧边栏项目。
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### 内容源
|
||||
|
||||
内容源处理您的所有内容,例如编译 Markdown 文件和验证前言。
|
||||
|
||||
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
|
||||
|
||||
<Tab value='Fumadocs MDX'>
|
||||
|
||||
阅读 [介绍](/docs/mdx) 了解它如何处理您的内容。
|
||||
|
||||
项目中已包含 `source.config.ts` 配置文件,您可以自定义不同的选项,如前言模式。
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Custom Source'>
|
||||
|
||||
Fumadocs 不仅限于 Markdown。对于其他源(如 Sanity),您可以构建 [自定义内容源](/docs/headless/custom-source)。
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### 自定义 UI
|
||||
|
||||
请参阅 [自定义指南](/docs/customisation)。
|
||||
|
||||
## 常见问题
|
||||
|
||||
您可能遇到的一些常见问题。
|
||||
|
||||
<Accordions>
|
||||
<Accordion id='fix-monorepo-styling' title="如何修复 Monorepo 中样式不应用的问题?">
|
||||
|
||||
有时,`fumadocs-ui` 没有安装在您的 Tailwind CSS 配置文件的工作区中(例如,在 monorepo 设置中)。
|
||||
|
||||
您必须确保 Tailwind CSS 扫描 `fumadocs-ui` 包,并为 `@source` 提供正确的相对路径。
|
||||
|
||||
例如,添加 `../../` 指向根工作区中的 `node_modules` 文件夹。
|
||||
|
||||
```css
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
/* [!code --] */
|
||||
@source '../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
/* [!code ++] */
|
||||
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='change-base-url' title="如何更改 /docs 的基本路由?">
|
||||
|
||||
您可以更改文档的基本路由(例如,从 `/docs/page` 更改为 `/info/page`)。
|
||||
由于 Fumadocs 使用 Next.js App Router,您可以简单地重命名路由:
|
||||
|
||||
<Files>
|
||||
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
<Folder name="app/info" defaultOpen>
|
||||
<File name="layout.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
并在 `source.ts` 中告诉 Fumadocs 使用新的路由:
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
baseUrl: '/info',
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='dynamic-route' title="它使用动态路由,性能会很差吗?">
|
||||
|
||||
当配置了 `generateStaticParams` 时,Next.js 会将动态路由转换为静态路由。
|
||||
因此,它与静态页面一样快。
|
||||
|
||||
您可以在 Next.js 上启用静态导出,获得静态构建输出。(请注意,路由处理器不适用于静态导出,您必须配置静态搜索)
|
||||
|
||||
</Accordion>
|
||||
<Accordion id='custom-layout-docs-page' title='如何在 /docs 中创建没有文档布局的页面?'>
|
||||
|
||||
与在 Next.js App Router 中管理布局相同,从内容目录(`/content/docs`)中删除原始 MDX 文件。
|
||||
这确保重复的页面不会导致错误。
|
||||
|
||||
现在,您可以将页面添加到另一个路由组,该组不是文档布局的后代。
|
||||
|
||||
例如,在您的 `app` 文件夹下:
|
||||
|
||||
<Files>
|
||||
<File name="(home)/docs/page.tsx" />
|
||||
<Folder name="docs">
|
||||
<File name="layout.tsx" />
|
||||
<File name="[[...slug]]/page.tsx" />
|
||||
</Folder>
|
||||
</Files>
|
||||
|
||||
将用您的 `page.tsx` 替换 `/docs` 页面。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-versions' title="如何实现多版本文档?">
|
||||
为每个版本使用单独的部署。
|
||||
|
||||
在 Vercel 上,可以通过在 GitHub 存储库中为特定版本创建另一个分支来实现。
|
||||
要链接到其他版本的站点,请使用 Links API 或自定义导航组件。
|
||||
</Accordion>
|
||||
|
||||
<Accordion id='multi-docs' title="如何实现多文档?">
|
||||
我们建议使用 [侧边栏标签](/docs/navigation/sidebar#sidebar-tabs)。
|
||||
</Accordion>
|
||||
|
||||
</Accordions>
|
||||
|
||||
## 视频教程
|
||||
|
||||
<YoutubeVideo url="https://www.youtube.com/embed/BPnK-YbISHQ?si=TH_tI3e4MCgMHzGr" />
|
||||
|
||||
## 了解更多
|
||||
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
222
content/docs/internationalization.mdx
Normal file
222
content/docs/internationalization.mdx
Normal file
@ -0,0 +1,222 @@
|
||||
---
|
||||
title: Internationalization
|
||||
description: Support multiple languages in your documentation
|
||||
---
|
||||
|
||||
<Callout title='Before you get started'>
|
||||
|
||||
Fumadocs is not a full-powered i18n library, it manages only its own components and utilities.
|
||||
|
||||
You can use other libraries like [next-intl](https://github.com/amannn/next-intl) for the rest of your app.
|
||||
Read the [Next.js Docs](https://nextjs.org/docs/app/building-your-application/routing/internationalization) to learn more about implementing I18n in Next.js.
|
||||
|
||||
</Callout>
|
||||
|
||||
## Manual Setup
|
||||
|
||||
Define the i18n configurations in a file, we will import it with `@/ilb/i18n` in this guide.
|
||||
|
||||
{/* <include cwd meta='title="lib/i18n.ts"'>
|
||||
../../examples/i18n/lib/i18n.ts
|
||||
</include> */}
|
||||
|
||||
Pass it to the source loader.
|
||||
|
||||
```ts title="lib/source.ts"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
|
||||
export const source = loader({
|
||||
i18n, // [!code highlight]
|
||||
// other options
|
||||
});
|
||||
```
|
||||
|
||||
And update Fumadocs UI layout options.
|
||||
|
||||
```tsx title="app/layout.config.tsx"
|
||||
import { i18n } from '@/lib/i18n';
|
||||
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
|
||||
|
||||
export function baseOptions(locale: string): BaseLayoutProps {
|
||||
return {
|
||||
i18n,
|
||||
// different props based on `locale`
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Middleware
|
||||
|
||||
Create a middleware that redirects users to appropriate locale.
|
||||
|
||||
```json doc-gen:file
|
||||
{
|
||||
"file": "../../examples/i18n/middleware.ts",
|
||||
"codeblock": {
|
||||
"lang": "ts",
|
||||
"meta": "title=\"middleware.ts\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See [Middleware](/docs/headless/internationalization#middleware) for customisable options.
|
||||
|
||||
> Note that this is optional, you can also use your own middleware or the one provided by i18n libraries.
|
||||
|
||||
### Routing
|
||||
|
||||
Create a `/app/[lang]` folder, and move all files (e.g. `page.tsx`, `layout.tsx`) from `/app` to the folder.
|
||||
|
||||
Wrap the root provider inside `I18nProvider`, and provide available languages & translations to it.
|
||||
Note that only English translations are provided by default.
|
||||
|
||||
```tsx title="app/[lang]/layout.tsx"
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
|
||||
|
||||
const cn: Partial<Translations> = {
|
||||
search: 'Translated Content',
|
||||
// other translations
|
||||
};
|
||||
|
||||
// available languages that will be displayed on UI
|
||||
// make sure `locale` is consistent with your i18n config
|
||||
const locales = [
|
||||
{
|
||||
name: 'English',
|
||||
locale: 'en',
|
||||
},
|
||||
{
|
||||
name: 'Chinese',
|
||||
locale: 'cn',
|
||||
},
|
||||
];
|
||||
|
||||
export default async function RootLayout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const lang = (await params).lang;
|
||||
|
||||
return (
|
||||
<html lang={lang}>
|
||||
<body>
|
||||
<I18nProvider
|
||||
locale={lang}
|
||||
locales={locales}
|
||||
translations={{ cn }[lang]}
|
||||
>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</I18nProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Pass Locale
|
||||
|
||||
Pass the locale to Fumadocs in your pages and layouts.
|
||||
|
||||
{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
|
||||
import type { ReactNode } from 'react';
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return (
|
||||
<DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```ts title="page.tsx" tab="Docs Page"
|
||||
import { source } from '@/lib/source';
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ lang: string; slug?: string[] }>;
|
||||
}) {
|
||||
const { slug, lang } = await params;
|
||||
// get page
|
||||
source.getPage(slug); // [!code --]
|
||||
source.getPage(slug, lang); // [!code ++]
|
||||
|
||||
// get pages
|
||||
source.getPages(); // [!code --]
|
||||
source.getPages(lang); // [!code ++]
|
||||
}
|
||||
``` */}
|
||||
|
||||
### Search
|
||||
|
||||
Configure i18n on your search solution.
|
||||
|
||||
- **Built-in Search (Orama):**
|
||||
For [Supported Languages](https://docs.orama.com/open-source/supported-languages#officially-supported-languages), no further changes are needed.
|
||||
|
||||
Otherwise, additional config is required (e.g. Chinese & Japanese). See [Special Languages](/docs/headless/search/orama#special-languages).
|
||||
|
||||
- **Cloud Solutions (e.g. Algolia):**
|
||||
They usually have official support for multilingual.
|
||||
|
||||
## Writing Documents
|
||||
|
||||
{/* <include>../../shared/page-conventions.i18n.mdx</include> */}
|
||||
|
||||
## Navigation
|
||||
|
||||
Fumadocs only handles navigation for its own layouts (e.g. sidebar).
|
||||
For other places, you can use the `useParams` hook to get the locale from url, and attend it to `href`.
|
||||
|
||||
```tsx
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
|
||||
const { lang } = useParams();
|
||||
|
||||
return <Link href={`/${lang}/another-page`}>This is a link</Link>;
|
||||
```
|
||||
|
||||
In addition, the [`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) component supports dynamic hrefs, you can use it to attend the locale prefix.
|
||||
It is useful for Markdown/MDX content.
|
||||
|
||||
```mdx title="content.mdx"
|
||||
import { DynamicLink } from 'fumadocs-core/dynamic-link';
|
||||
|
||||
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user