Compare commits
660 Commits
dev/fumado
...
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 |
@ -5,6 +5,10 @@
|
||||
"args": [
|
||||
"~/.console-ninja/mcp/"
|
||||
]
|
||||
},
|
||||
"context7": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@upstash/context7-mcp@latest"]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for using Vercel AI SDK
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
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
|
@ -1,10 +1,10 @@
|
||||
---
|
||||
description: Best practices for date and time manipulation with date-fns
|
||||
globs: **/*.{ts,tsx,js,jsx}
|
||||
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.
|
||||
- Leverage the `isWithinInterval` function for date range checks.
|
||||
|
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
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
description: Best practices for using Drizzle ORM with database
|
||||
globs: **/*.{ts}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Use Drizzle's type-safe query builder for better code completion and safety.
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for Next.js applications and routing
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
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
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for using Radix UI components
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for React component development
|
||||
globs: **/*.{ts,tsx,js,jsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
---
|
||||
description: Best practices for form handling with React Hook Form
|
||||
globs: **/*.{ts,tsx}
|
||||
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.
|
||||
- Leverage the `useFormContext` hook for sharing form state across components.
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for integrating Stripe payments
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Best practices for styling with Tailwind CSS
|
||||
globs: **/*.{ts,tsx,css}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: TypeScript coding standards and type safety guidelines
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
@ -11,4 +11,4 @@ alwaysApply: false
|
||||
- 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.
|
||||
- Use `pnpm` as default package manager if run Command in Terminal.
|
||||
|
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
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
description: Best practices for schema validation with Zod
|
||||
globs: **/*.{ts,tsx}
|
||||
globs: *.tsx,*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
- Define clear and reusable schemas for data validation
|
||||
|
@ -1,10 +1,10 @@
|
||||
---
|
||||
description: Best practices for state management with Zustand
|
||||
globs: **/*.{ts,tsx}
|
||||
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.
|
||||
- Leverage the `immer` middleware for easier state updates with mutable syntax.
|
||||
|
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
|
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
|
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.
|
25
.gitignore
vendored
@ -30,15 +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
|
||||
.content-collections
|
||||
|
||||
# fumadocs
|
||||
.source
|
||||
|
||||
# OpenNext build output
|
||||
.open-next
|
||||
|
||||
# wrangler files
|
||||
.wrangler
|
||||
.dev.vars
|
||||
.dev.vars*
|
||||
!.dev.vars.example
|
||||
|
5
.vscode/extensions.json
vendored
@ -2,6 +2,9 @@
|
||||
"recommendations": [
|
||||
"biomejs.biome",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"Lokalise.i18n-ally"
|
||||
"Lokalise.i18n-ally",
|
||||
"unifiedjs.vscode-mdx",
|
||||
"eamodio.gitlens",
|
||||
"editorconfig.editorconfig"
|
||||
]
|
||||
}
|
||||
|
14
.vscode/settings.json
vendored
@ -20,6 +20,16 @@
|
||||
"source.organizeImports.biome": "explicit"
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true
|
||||
"**/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
@ -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
@ -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"]
|
34
README.md
@ -1,12 +1,12 @@
|
||||
# MkSaaS
|
||||
|
||||
Make AI SaaS in days, simply and effortlessly.
|
||||
Make AI SaaS in a weekend.
|
||||
|
||||
MkSaaS is a complete Next.js boilerplate for building AI SaaS websites. Make money from day one with our battle-tested stack and built-in monetization features.
|
||||
The complete Next.js boilerplate for building profitable SaaS, with auth, payments, i18n, newsletter, dashboard, blog, docs, blocks, themes, SEO and more.
|
||||
|
||||
## Author
|
||||
|
||||
This project is created by [Fox](https://x.com/indie_maker_fox), the founder of MkSaaS LLC and the creator of [Mkdirs](https://mkdirs.com), [IndieHub](https://indiehub.best) and some other websites.
|
||||
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.
|
||||
|
||||
## Documentation
|
||||
|
||||
@ -16,22 +16,30 @@ If you found anything that could be improved, please let me know.
|
||||
|
||||
## Links
|
||||
|
||||
- website: [mksaas.com](https://mksaas.com)
|
||||
- demo: [demo.mksaas.com](https://demo.mksaas.com)
|
||||
- discord: [https://discord.gg/yVwpEtTT](https://discord.gg/yVwpEtTT)
|
||||
- documentation (WIP): [mksaas.com/docs](https://mksaas.com/docs)
|
||||
- video (WIP): [www.youtube.com/@MkSaaSHQ](https://www.youtube.com/@MkSaaSHQ)
|
||||
- roadmap (WIP): [issues/17](https://github.com/MkSaaSHQ/mksaas-template/issues/17)
|
||||
- 🔥 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)
|
||||
|
||||
## Repositories
|
||||
|
||||
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.
|
||||
|
||||
- [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
|
||||
|
||||
## 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).
|
||||
|
||||
> If you have any feature requests or questions or ideas to share, please [submit it in the discussions](https://github.com/MkSaaSHQ/mksaas-template/discussions).
|
||||
> 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 or discussions of the repository, please use **English** as the main Language, so that everyone can read it and help you, thank you for your supports.
|
||||
> 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
|
||||
|
||||
|
35
biome.json
@ -9,22 +9,28 @@
|
||||
"ignoreUnknown": true,
|
||||
"ignore": [
|
||||
".next/**",
|
||||
".open-next/**",
|
||||
".wrangler/**",
|
||||
".cursor/**",
|
||||
".claude/**",
|
||||
".kiro/**",
|
||||
".conductor/**",
|
||||
".vscode/**",
|
||||
".content-collections/**",
|
||||
".source/**",
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
"build/**",
|
||||
"drizzle/**",
|
||||
"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/db/schema.ts",
|
||||
"src/payment/types.ts",
|
||||
"src/types/index.d.ts",
|
||||
"public/sw.js"
|
||||
"src/credits/types.ts",
|
||||
"src/types/index.d.ts"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
@ -32,7 +38,8 @@
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 80,
|
||||
"formatWithErrors": true
|
||||
"formatWithErrors": true,
|
||||
"useEditorconfig": true
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
@ -67,22 +74,28 @@
|
||||
},
|
||||
"ignore": [
|
||||
".next/**",
|
||||
".open-next/**",
|
||||
".wrangler/**",
|
||||
".cursor/**",
|
||||
".claude/**",
|
||||
".conductor/**",
|
||||
".kiro/**",
|
||||
".vscode/**",
|
||||
".content-collections/**",
|
||||
".source/**",
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
"build/**",
|
||||
"drizzle/**",
|
||||
"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/db/schema.ts",
|
||||
"src/payment/types.ts",
|
||||
"src/types/index.d.ts",
|
||||
"public/sw.js"
|
||||
"src/credits/types.ts",
|
||||
"src/types/index.d.ts"
|
||||
]
|
||||
},
|
||||
"javascript": {
|
||||
|
7483
cloudflare-env.d.ts
vendored
Normal file
@ -1,328 +0,0 @@
|
||||
import path from 'path';
|
||||
import { DEFAULT_LOCALE, LOCALES } from '@/i18n/routing';
|
||||
import { defineCollection, defineConfig } from '@content-collections/core';
|
||||
import {
|
||||
createDocSchema,
|
||||
createMetaSchema,
|
||||
transformMDX,
|
||||
} from '@fumadocs/content-collections/configuration';
|
||||
|
||||
/**
|
||||
* 1. Content Collections documentation
|
||||
* https://www.content-collections.dev/docs/quickstart/next
|
||||
* https://www.content-collections.dev/docs/configuration
|
||||
* https://www.content-collections.dev/docs/transform#join-collections
|
||||
*
|
||||
* 2. Use Content Collections for Fumadocs
|
||||
* https://fumadocs.vercel.app/docs/headless/content-collections
|
||||
*/
|
||||
const docs = defineCollection({
|
||||
name: 'docs',
|
||||
directory: 'content/docs',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
...createDocSchema(z),
|
||||
preview: z.string().optional(),
|
||||
index: z.boolean().default(false),
|
||||
}),
|
||||
transform: transformMDX,
|
||||
});
|
||||
|
||||
const metas = defineCollection({
|
||||
name: 'meta',
|
||||
directory: 'content/docs',
|
||||
include: '**/meta**.json',
|
||||
parser: 'json',
|
||||
schema: createMetaSchema,
|
||||
});
|
||||
|
||||
/**
|
||||
* Blog Author collection
|
||||
*
|
||||
* Authors are identified by their slug across all languages
|
||||
* New format: content/author/authorname.{locale}.mdx
|
||||
* Example: content/author/mksaas.mdx (default locale) and content/author/mksaas.zh.mdx (Chinese)
|
||||
*
|
||||
* For author, slug is slugAsParams
|
||||
*/
|
||||
export const authors = defineCollection({
|
||||
name: 'author',
|
||||
directory: 'content/author',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
slug: z.string(),
|
||||
name: z.string(),
|
||||
avatar: z.string(),
|
||||
locale: z.string().optional().default(DEFAULT_LOCALE),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`author processed: ${fileName}, locale=${locale}`);
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Blog Category collection
|
||||
*
|
||||
* Categories are identified by their slug across all languages
|
||||
* New format: content/category/categoryname.{locale}.mdx
|
||||
* Example: content/category/tutorial.mdx (default locale) and content/category/tutorial.zh.mdx (Chinese)
|
||||
*
|
||||
* For category, slug is slugAsParams
|
||||
*/
|
||||
export const categories = defineCollection({
|
||||
name: 'category',
|
||||
directory: 'content/category',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
slug: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
locale: z.string().optional().default(DEFAULT_LOCALE),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`category processed: ${fileName}, locale=${locale}`);
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Blog Post collection
|
||||
*
|
||||
* New format: content/blog/post-slug.{locale}.mdx
|
||||
*
|
||||
* slug: /blog/first-post, used in URL or sitemap
|
||||
* slugAsParams: first-post, used in route params
|
||||
*
|
||||
* 1. For a blog post at content/blog/first-post.mdx (default locale):
|
||||
* locale: en
|
||||
* slug: /blog/first-post
|
||||
* slugAsParams: first-post
|
||||
*
|
||||
* 2. For a blog post at content/blog/first-post.zh.mdx (Chinese locale):
|
||||
* locale: zh
|
||||
* slug: /blog/first-post
|
||||
* slugAsParams: first-post
|
||||
*/
|
||||
export const posts = defineCollection({
|
||||
name: 'post',
|
||||
directory: 'content/blog',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
image: z.string(),
|
||||
date: z.string().datetime(),
|
||||
published: z.boolean().default(true),
|
||||
categories: z.array(z.string()),
|
||||
author: z.string(),
|
||||
estimatedTime: z.number().optional(), // Reading time in minutes
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Use Fumadocs transformMDX for consistent MDX processing
|
||||
const transformedData = await transformMDX(data, context);
|
||||
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`post processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
|
||||
// Find the author by matching slug and locale
|
||||
const blogAuthor = context
|
||||
.documents(authors)
|
||||
.find((a) => a.slug === data.author && a.locale === locale);
|
||||
|
||||
// Find categories by matching slug and locale
|
||||
const blogCategories = data.categories
|
||||
.map((categorySlug) => {
|
||||
const category = context
|
||||
.documents(categories)
|
||||
.find((c) => c.slug === categorySlug && c.locale === locale);
|
||||
|
||||
return category;
|
||||
})
|
||||
.filter(Boolean); // Remove null values
|
||||
|
||||
// Create the slug and slugAsParams
|
||||
const slug = `/blog/${base}`;
|
||||
const slugAsParams = base;
|
||||
|
||||
// Calculate estimated reading time
|
||||
const wordCount = data.content.split(/\s+/).length;
|
||||
const wordsPerMinute = 200; // average reading speed: 200 words per minute
|
||||
const estimatedTime = Math.max(Math.ceil(wordCount / wordsPerMinute), 1);
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
author: blogAuthor,
|
||||
categories: blogCategories,
|
||||
slug,
|
||||
slugAsParams,
|
||||
estimatedTime,
|
||||
body: transformedData.body,
|
||||
toc: transformedData.toc,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Pages collection for policy pages like privacy-policy, terms-of-service, etc.
|
||||
*
|
||||
* New format: content/pages/page-slug.{locale}.mdx
|
||||
*
|
||||
* 1. For a page at content/pages/privacy-policy.mdx (default locale):
|
||||
* locale: en
|
||||
* slug: /pages/privacy-policy
|
||||
* slugAsParams: privacy-policy
|
||||
*
|
||||
* 2. For a page at content/pages/privacy-policy.zh.mdx (Chinese locale):
|
||||
* locale: zh
|
||||
* slug: /pages/privacy-policy
|
||||
* slugAsParams: privacy-policy
|
||||
*/
|
||||
export const pages = defineCollection({
|
||||
name: 'page',
|
||||
directory: 'content/pages',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Use Fumadocs transformMDX for consistent MDX processing
|
||||
const transformedData = await transformMDX(data, context);
|
||||
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`page processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
|
||||
// Create the slug and slugAsParams
|
||||
const slug = `/pages/${base}`;
|
||||
const slugAsParams = base;
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
slug,
|
||||
slugAsParams,
|
||||
body: transformedData.body,
|
||||
toc: transformedData.toc,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Releases collection for changelog
|
||||
*
|
||||
* New format: content/release/version-slug.{locale}.mdx
|
||||
*
|
||||
* 1. For a release at content/release/v1-0-0.mdx (default locale):
|
||||
* locale: en
|
||||
* slug: /release/v1-0-0
|
||||
* slugAsParams: v1-0-0
|
||||
*
|
||||
* 2. For a release at content/release/v1-0-0.zh.mdx (Chinese locale):
|
||||
* locale: zh
|
||||
* slug: /release/v1-0-0
|
||||
* slugAsParams: v1-0-0
|
||||
*/
|
||||
export const releases = defineCollection({
|
||||
name: 'release',
|
||||
directory: 'content/release',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
version: z.string(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Use Fumadocs transformMDX for consistent MDX processing
|
||||
const transformedData = await transformMDX(data, context);
|
||||
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`release processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
|
||||
// Create the slug and slugAsParams
|
||||
const slug = `/release/${base}`;
|
||||
const slugAsParams = base;
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
slug,
|
||||
slugAsParams,
|
||||
body: transformedData.body,
|
||||
toc: transformedData.toc,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper function to extract locale and base name from filename
|
||||
* Handles filename formats:
|
||||
* - name -> locale: DEFAULT_LOCALE, base: name
|
||||
* - name.zh -> locale: zh, base: name
|
||||
*
|
||||
* @param fileName Filename without extension (already has .mdx removed)
|
||||
* @returns Object with locale and base name
|
||||
*/
|
||||
function extractLocaleAndBase(fileName: string): {
|
||||
locale: string;
|
||||
base: string;
|
||||
} {
|
||||
// Split filename into parts
|
||||
const parts = fileName.split('.');
|
||||
|
||||
if (parts.length === 1) {
|
||||
// Simple filename without locale: xxx
|
||||
return { locale: DEFAULT_LOCALE, base: parts[0] };
|
||||
}
|
||||
if (parts.length === 2 && LOCALES.includes(parts[1])) {
|
||||
// Filename with locale: xxx.zh
|
||||
return { locale: parts[1], base: parts[0] };
|
||||
}
|
||||
// Unexpected format, use first part as base and default locale
|
||||
console.warn(`Unexpected filename format: ${fileName}`);
|
||||
return { locale: DEFAULT_LOCALE, base: parts[0] };
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
collections: [docs, metas, authors, categories, posts, pages, releases],
|
||||
});
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: fox
|
||||
name: Fox
|
||||
avatar: /images/avatars/fox.png
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: fox
|
||||
name: Fox
|
||||
avatar: /images/avatars/fox.png
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: mkdirs
|
||||
name: Mkdirs
|
||||
avatar: /images/avatars/mkdirs.png
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: mkdirs
|
||||
name: Mkdirs模板
|
||||
avatar: /images/avatars/mkdirs.png
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: mksaas
|
||||
name: MkSaaS
|
||||
avatar: /images/avatars/mksaas.png
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: mksaas
|
||||
name: MkSaaS模板
|
||||
avatar: /images/avatars/mksaas.png
|
||||
---
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Comparisons
|
||||
description: How is Fumadocs different from other existing frameworks?
|
||||
image: /images/blog/post-2.png
|
||||
date: 2025-03-22T12:00:00.000Z
|
||||
date: "2025-03-22"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 对比
|
||||
description: Fumadocs 与其他现有框架有何不同?
|
||||
image: /images/blog/post-2.png
|
||||
date: 2025-03-22T12:00:00.000Z
|
||||
date: "2025-03-22"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
@ -69,4 +69,4 @@ Docusaurus 是一个基于 React.js 的强大框架。它通过插件和自定
|
||||
|
||||
您可以通过插件轻松实现许多功能,他们的生态系统确实更大,并由许多贡献者维护。
|
||||
|
||||
相比之下,Fumadocs 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。
|
||||
相比之下,Fumadocs 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。
|
@ -2,7 +2,7 @@
|
||||
title: Quick Start
|
||||
description: Getting Started with Fumadocs
|
||||
image: /images/blog/post-8.png
|
||||
date: 2025-03-28T12:00:00.000Z
|
||||
date: "2025-03-28"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
@ -99,7 +99,7 @@ title: Hello World
|
||||
|
||||
Run the app in development mode and see http://localhost:3000/docs.
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 快速入门
|
||||
description: Fumadocs 入门指南
|
||||
image: /images/blog/post-8.png
|
||||
date: 2025-03-28T12:00:00.000Z
|
||||
date: "2025-03-28"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
@ -99,7 +99,7 @@ title: Hello World
|
||||
|
||||
在开发模式下运行应用程序并查看 http://localhost:3000/docs。
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
@ -250,4 +250,4 @@ export const source = loader({
|
||||
|
||||
## 了解更多
|
||||
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Internationalization
|
||||
description: Support multiple languages in your documentation
|
||||
image: /images/blog/post-3.png
|
||||
date: 2025-03-15T12:00:00.000Z
|
||||
date: "2025-03-15"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 国际化
|
||||
description: 在您的文档中支持多种语言
|
||||
image: /images/blog/post-3.png
|
||||
date: 2025-03-15T12:00:00.000Z
|
||||
date: "2025-03-15"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
@ -224,4 +224,4 @@ return <Link href={`/${lang}/another-page`}>This is a link</Link>;
|
||||
import { DynamicLink } from 'fumadocs-core/dynamic-link';
|
||||
|
||||
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
|
||||
```
|
||||
```
|
@ -2,7 +2,7 @@
|
||||
title: Manual Installation
|
||||
description: Create a new fumadocs project from scratch.
|
||||
image: /images/blog/post-4.png
|
||||
date: 2025-03-14T12:00:00.000Z
|
||||
date: "2025-03-14"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
@ -14,7 +14,7 @@ author: mkdirs
|
||||
|
||||
Create a new Next.js application with `create-next-app`, and install required packages.
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 手动安装
|
||||
description: 从零开始创建一个新的 Fumadocs 项目
|
||||
image: /images/blog/post-4.png
|
||||
date: 2025-03-14T12:00:00.000Z
|
||||
date: "2025-03-14"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
@ -14,7 +14,7 @@ author: mkdirs
|
||||
|
||||
使用 `create-next-app` 创建一个新的 Next.js 应用程序,并安装所需的包。
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
@ -193,4 +193,4 @@ WORKDIR /app
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
|
||||
```
|
||||
|
||||
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。
|
||||
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Markdown
|
||||
description: How to write documents
|
||||
image: /images/blog/post-5.png
|
||||
date: 2025-03-05T12:00:00.000Z
|
||||
date: "2025-03-05"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
@ -353,12 +353,12 @@ Some optional plugins you can enable.
|
||||
Write math equations with TeX.
|
||||
|
||||
````md
|
||||
```math
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
````
|
||||
|
||||
```math
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
|
||||
@ -369,12 +369,12 @@ To enable, see [Math Integration](/docs/math).
|
||||
Generate code blocks for installing packages via package managers (JS/Node.js).
|
||||
|
||||
````md
|
||||
```package-install
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
````
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Markdown
|
||||
description: 如何撰写文档
|
||||
image: /images/blog/post-5.png
|
||||
date: 2025-03-05T12:00:00.000Z
|
||||
date: "2025-03-05"
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
@ -251,7 +251,7 @@ console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
### 高亮行
|
||||
### 高亮行
|
||||
|
||||
````md
|
||||
```tsx
|
||||
|
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
@ -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>
|
@ -2,7 +2,7 @@
|
||||
title: Search
|
||||
description: Implement document search in your docs
|
||||
image: /images/blog/post-6.png
|
||||
date: 2025-02-15T12:00:00.000Z
|
||||
date: "2025-02-15"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 搜索
|
||||
description: 在您的文档中实现文档搜索
|
||||
image: /images/blog/post-6.png
|
||||
date: 2025-02-15T12:00:00.000Z
|
||||
date: "2025-02-15"
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
@ -249,4 +249,4 @@ export default function CustomSearchDialog(props: SharedProps) {
|
||||
```
|
||||
|
||||
1. 将 `endpoint`、`apiKey` 替换为您想要的值。
|
||||
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。
|
||||
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。
|
@ -2,7 +2,7 @@
|
||||
title: Themes
|
||||
description: Add Theme to Fumadocs UI
|
||||
image: /images/blog/post-7.png
|
||||
date: 2025-01-15T12:00:00.000Z
|
||||
date: "2025-01-15"
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 主题
|
||||
description: 为 Fumadocs UI 添加主题
|
||||
image: /images/blog/post-7.png
|
||||
date: 2025-01-15T12:00:00.000Z
|
||||
date: "2025-01-15"
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
@ -167,4 +167,4 @@ Tailwind CSS 预设引入了新的颜色和额外的工具,包括 `fd-steps`
|
||||
```
|
||||
|
||||
> 该插件仅与 Fumadocs UI 的 MDX 组件一起工作,它可能与 `@tailwindcss/typography` 冲突。
|
||||
> 如果您需要使用 `@tailwindcss/typography` 而不是默认插件,请[设置类名选项](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name)以避免冲突。
|
||||
> 如果您需要使用 `@tailwindcss/typography` 而不是默认插件,请[设置类名选项](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name)以避免冲突。
|
@ -2,7 +2,7 @@
|
||||
title: What is Fumadocs
|
||||
description: Introducing Fumadocs, a docs framework that you can break.
|
||||
image: /images/blog/post-1.png
|
||||
date: 2025-04-01T12:00:00.000Z
|
||||
date: "2025-04-01"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 什么是 Fumadocs
|
||||
description: 介绍 Fumadocs,一个可以打破常规的文档框架
|
||||
image: /images/blog/post-1.png
|
||||
date: 2025-04-01T12:00:00.000Z
|
||||
date: "2025-04-01"
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
@ -57,4 +57,4 @@ Fumadocs 为 Next.js 提供了额外的工具,包括语法高亮、文档搜
|
||||
|
||||
Fumadocs 由 Fuma 和许多贡献者维护,关注代码库的可维护性。
|
||||
虽然我们不打算提供人们想要的每一项功能,但我们更专注于使基本功能完美且维护良好。
|
||||
您也可以通过贡献来帮助 Fumadocs 变得更加有用!
|
||||
您也可以通过贡献来帮助 Fumadocs 变得更加有用!
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: company
|
||||
name: Company
|
||||
description: Company news and updates
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: company
|
||||
name: 公司
|
||||
description: 公司新闻和更新
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: news
|
||||
name: News
|
||||
description: News and updates about MkSaaS
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: news
|
||||
name: 新闻
|
||||
description: 最新新闻和更新
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: product
|
||||
name: Product
|
||||
description: Products and services powered by MkSaaS
|
||||
---
|
||||
|
@ -1,5 +1,4 @@
|
||||
---
|
||||
slug: product
|
||||
name: 产品
|
||||
description: 产品和服务
|
||||
---
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Initial Release"
|
||||
description: "Our first official release with core features and functionality"
|
||||
date: "2024-03-01T00:00:00Z"
|
||||
date: "2024-03-01"
|
||||
version: "v1.0.0"
|
||||
published: true
|
||||
---
|
||||
@ -27,4 +27,4 @@ We're excited to announce the initial release of our platform with the following
|
||||
|
||||
- Fixed issues with user registration flow
|
||||
- Resolved authentication token expiration handling
|
||||
- Improved form validation and error messages
|
||||
- Improved form validation and error messages
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "初始版本"
|
||||
description: "我们的第一个正式版本,包含核心功能"
|
||||
date: "2024-03-01T00:00:00Z"
|
||||
date: "2024-03-01"
|
||||
version: "v1.0.0"
|
||||
published: true
|
||||
---
|
||||
@ -27,4 +27,4 @@ published: true
|
||||
|
||||
- 修复了用户注册流程中的问题
|
||||
- 解决了身份验证令牌过期处理
|
||||
- 改进了表单验证和错误消息
|
||||
- 改进了表单验证和错误消息
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Feature Update"
|
||||
description: "New features and improvements to enhance your experience"
|
||||
date: "2024-03-15T00:00:00Z"
|
||||
date: "2024-03-15"
|
||||
version: "v1.1.0"
|
||||
published: true
|
||||
---
|
||||
@ -27,4 +27,4 @@ We've added several new features to improve your experience:
|
||||
- Fixed issue with project duplication
|
||||
- Resolved calendar sync problems
|
||||
- Fixed data import validation errors
|
||||
- Improved error handling for API requests
|
||||
- Improved error handling for API requests
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "功能更新"
|
||||
description: "新功能和改进,提升您的使用体验"
|
||||
date: "2024-03-15T00:00:00Z"
|
||||
date: "2024-03-15"
|
||||
version: "v1.1.0"
|
||||
published: true
|
||||
---
|
||||
@ -27,4 +27,4 @@ published: true
|
||||
- 修复了项目复制问题
|
||||
- 解决了日历同步问题
|
||||
- 修复了数据导入验证错误
|
||||
- 改进了API请求的错误处理
|
||||
- 改进了API请求的错误处理
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "AI Integration"
|
||||
description: "Introducing AI-powered features to boost productivity"
|
||||
date: "2024-03-30T00:00:00Z"
|
||||
date: "2024-03-30"
|
||||
version: "v1.2.0"
|
||||
published: true
|
||||
---
|
||||
@ -34,4 +34,4 @@ We're thrilled to introduce our new AI capabilities:
|
||||
- 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
|
||||
- Fixed accessibility issues in the dashboard
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "AI集成"
|
||||
description: "引入AI驱动的功能,提高生产力"
|
||||
date: "2024-03-30T00:00:00Z"
|
||||
date: "2024-03-30"
|
||||
version: "v1.2.0"
|
||||
published: true
|
||||
---
|
||||
@ -34,4 +34,4 @@ published: true
|
||||
- 修复了某些浏览器上文件上传的问题
|
||||
- 解决了设备之间的同步问题
|
||||
- 改进了第三方集成的错误处理
|
||||
- 修复了仪表板中的可访问性问题
|
||||
- 修复了仪表板中的可访问性问题
|
@ -2,4 +2,4 @@
|
||||
title: 组件
|
||||
description: 改进文档的额外组件
|
||||
index: true
|
||||
---
|
||||
---
|
||||
|
@ -46,6 +46,6 @@ Since the design system is built on Tailwind CSS, you can customise it [with CSS
|
||||
|
||||
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:
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npx fumadocs add
|
||||
```
|
||||
|
@ -46,6 +46,6 @@ Fumadocs UI 还提供了样式化组件,用于交互式示例以增强您的
|
||||
|
||||
如果这些都不适合您,Fumadocs CLI 是一个工具,可以将 Fumadocs UI 组件和布局安装到您的代码库中,类似于 Shadcn UI。允许您完全自定义 Fumadocs UI:
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npx fumadocs add
|
||||
```
|
||||
```
|
||||
|
@ -95,7 +95,7 @@ title: Hello World
|
||||
|
||||
Run the app in development mode and see http://localhost:3000/docs.
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
@ -244,6 +244,10 @@ will replace the `/docs` page with your `page.tsx`.
|
||||
|
||||
</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.
|
||||
|
@ -95,7 +95,7 @@ title: Hello World
|
||||
|
||||
在开发模式下运行应用程序并查看 http://localhost:3000/docs。
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm run dev
|
||||
```
|
||||
|
||||
@ -244,6 +244,10 @@ export const source = loader({
|
||||
|
||||
</Accordions>
|
||||
|
||||
## 视频教程
|
||||
|
||||
<YoutubeVideo url="https://www.youtube.com/embed/BPnK-YbISHQ?si=TH_tI3e4MCgMHzGr" />
|
||||
|
||||
## 了解更多
|
||||
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
||||
|
@ -9,7 +9,7 @@ description: Create a new fumadocs project from scratch.
|
||||
|
||||
Create a new Next.js application with `create-next-app`, and install required packages.
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
|
@ -9,7 +9,7 @@ description: 从零开始创建一个新的 Fumadocs 项目
|
||||
|
||||
使用 `create-next-app` 创建一个新的 Next.js 应用程序,并安装所需的包。
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
fumadocs-ui fumadocs-core
|
||||
```
|
||||
|
||||
@ -188,4 +188,4 @@ WORKDIR /app
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
|
||||
```
|
||||
|
||||
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。
|
||||
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。
|
||||
|
@ -337,6 +337,8 @@ Images are automatically optimized for `next/image`.
|
||||

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

|
||||
|
||||
## Optional
|
||||
|
||||
Some optional plugins you can enable.
|
||||
@ -346,12 +348,12 @@ Some optional plugins you can enable.
|
||||
Write math equations with TeX.
|
||||
|
||||
````md
|
||||
```math
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
````
|
||||
|
||||
```math
|
||||
```mdx
|
||||
f(x) = x * e^{2 pi i \xi x}
|
||||
```
|
||||
|
||||
@ -362,12 +364,12 @@ To enable, see [Math Integration](/docs/math).
|
||||
Generate code blocks for installing packages via package managers (JS/Node.js).
|
||||
|
||||
````md
|
||||
```package-install
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
````
|
||||
|
||||
```package-install
|
||||
```mdx
|
||||
npm i next -D
|
||||
```
|
||||
|
||||
|
@ -246,7 +246,7 @@ console.log('Hello World');
|
||||
```
|
||||
````
|
||||
|
||||
### 高亮行
|
||||
### 高亮行
|
||||
|
||||
````md
|
||||
```tsx
|
||||
@ -335,6 +335,8 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||

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

|
||||
|
||||
## 可选功能
|
||||
|
||||
一些您可以启用的可选插件。
|
||||
|
@ -2,6 +2,7 @@
|
||||
title: What is Fumadocs
|
||||
description: Introducing Fumadocs, a docs framework that you can break.
|
||||
icon: CircleHelp
|
||||
premium: true
|
||||
---
|
||||
|
||||
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**.
|
||||
@ -18,6 +19,8 @@ You are still using features of Next.js App Router, like **Static Site Generatio
|
||||
**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.
|
||||
|
||||
<PremiumContent>
|
||||
|
||||
## Why Fumadocs
|
||||
|
||||
Fumadocs is designed with flexibility in mind.
|
||||
@ -56,3 +59,5 @@ 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!
|
||||
|
||||
</PremiumContent>
|
||||
|
@ -2,6 +2,7 @@
|
||||
title: 什么是 Fumadocs
|
||||
description: 介绍 Fumadocs,一个可以打破常规的文档框架
|
||||
icon: CircleHelp
|
||||
premium: true
|
||||
---
|
||||
|
||||
Fumadocs 的创建是因为我想要一种更加可定制化的文档构建体验,一个不固执己见的文档框架,**一个你可以"打破"的"框架"**。
|
||||
@ -18,6 +19,8 @@ Fumadocs 的创建是因为我想要一种更加可定制化的文档构建体
|
||||
**对 UI 有自己的看法:** Fumadocs UI(默认主题)提供的唯一东西是**用户界面**。UI 的设计理念是提供更好的移动响应性和用户体验。
|
||||
相反,我们使用受 Shadcn UI 启发的更灵活的方法 — [Fumadocs CLI](/docs/cli),这样我们可以快速迭代设计,并欢迎更多关于 UI 的反馈。
|
||||
|
||||
<PremiumContent>
|
||||
|
||||
## 为什么选择 Fumadocs
|
||||
|
||||
Fumadocs 的设计考虑了灵活性。
|
||||
@ -53,4 +56,6 @@ Fumadocs 为 Next.js 提供了额外的工具,包括语法高亮、文档搜
|
||||
|
||||
Fumadocs 由 Fuma 和许多贡献者维护,关注代码库的可维护性。
|
||||
虽然我们不打算提供人们想要的每一项功能,但我们更专注于使基本功能完美且维护良好。
|
||||
您也可以通过贡献来帮助 Fumadocs 变得更加有用!
|
||||
您也可以通过贡献来帮助 Fumadocs 变得更加有用!
|
||||
|
||||
</PremiumContent>
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Cookie Policy
|
||||
description: How we use cookies and similar technologies on our website
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Cookie 政策
|
||||
description: 我们如何在网站上使用 Cookie 和类似技术
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Privacy Policy
|
||||
description: Our commitment to protecting your privacy and personal data
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 隐私政策
|
||||
description: 我们致力于保护您的隐私和个人数据
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Terms of Service
|
||||
description: The terms and conditions governing the use of our services
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 服务条款
|
||||
description: 管理我们服务使用的条款和条件
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
1
dev.vars.example
Normal file
@ -0,0 +1 @@
|
||||
NEXTJS_ENV=development
|
@ -5,7 +5,7 @@ import { defineConfig } from 'drizzle-kit';
|
||||
* https://orm.drizzle.team/docs/get-started/neon-new#step-5---setup-drizzle-config-file
|
||||
*/
|
||||
export default defineConfig({
|
||||
out: './drizzle',
|
||||
out: './src/db/migrations',
|
||||
schema: './src/db/schema.ts',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1744304844165,
|
||||
"tag": "0000_fine_sir_ram",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
126
env.example
@ -1,5 +1,6 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# Application BASE URL
|
||||
# https://mksaas.com/docs/env#core-configuration
|
||||
# For production, set to your domain, e.g. https://mksaas.com
|
||||
# For development, set to http://localhost:3000 or any other port
|
||||
# -----------------------------------------------------------------------------
|
||||
@ -7,57 +8,60 @@ NEXT_PUBLIC_BASE_URL="http://localhost:3000"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Database
|
||||
# https://orm.drizzle.team/docs/get-started/neon-new
|
||||
# https://orm.drizzle.team/docs/connect-supabase
|
||||
# https://mksaas.com/docs/database
|
||||
# -----------------------------------------------------------------------------
|
||||
DATABASE_URL=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Better Auth
|
||||
# https://www.better-auth.com/docs/installation
|
||||
# https://mksaas.com/docs/auth
|
||||
# Generate a random string for the secret key using `openssl rand -base64 32`
|
||||
# -----------------------------------------------------------------------------
|
||||
BETTER_AUTH_SECRET=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Github OAuth
|
||||
# https://mksaas.com/docs/auth#2-configure-github-oauth
|
||||
# https://www.better-auth.com/docs/authentication/github
|
||||
# Get Client ID and Client Secret from https://github.com/settings/developers
|
||||
# Get Client information from https://github.com/settings/developers
|
||||
# -----------------------------------------------------------------------------
|
||||
GITHUB_CLIENT_ID=""
|
||||
GITHUB_CLIENT_SECRET=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Google OAuth
|
||||
# https://mksaas.com/docs/auth#3-configure-google-oauth
|
||||
# https://www.better-auth.com/docs/authentication/google
|
||||
# Get Client ID and Client Secret from https://console.cloud.google.com/apis/credentials
|
||||
# Get Client information from https://console.cloud.google.com/apis/credentials
|
||||
# -----------------------------------------------------------------------------
|
||||
GOOGLE_CLIENT_ID=""
|
||||
GOOGLE_CLIENT_SECRET=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Email (Resend)
|
||||
# https://resend.com/docs/api-reference/introduction
|
||||
# https://resend.com/docs/dashboard/audiences/contacts
|
||||
# Email / Newsletter (Resend)
|
||||
# https://mksaas.com/docs/email
|
||||
# https://mksaas.com/docs/newsletter
|
||||
# Get API key and audience id from https://resend.com
|
||||
# -----------------------------------------------------------------------------
|
||||
RESEND_API_KEY=""
|
||||
RESEND_AUDIENCE_ID=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Storage (Cloudflare R2 or S3-compatible service of your choice)
|
||||
# https://www.npmjs.com/package/@aws-sdk/client-s3
|
||||
# https://mksaas.com/docs/storage
|
||||
# Cloudflare R2: https://www.cloudflare.com/developer-platform/products/r2
|
||||
# -----------------------------------------------------------------------------
|
||||
STORAGE_REGION="auto"
|
||||
STORAGE_BUCKET_NAME=""
|
||||
STORAGE_ACCESS_KEY_ID=""
|
||||
STORAGE_SECRET_ACCESS_KEY=""
|
||||
STORAGE_ENDPOINT=""
|
||||
STORAGE_FORCE_PATH_STYLE="false"
|
||||
STORAGE_PUBLIC_URL=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Payment (Stripe)
|
||||
# https://stripe.com/docs/keys
|
||||
# https://mksaas.com/docs/payment
|
||||
# Get Stripe key and secret from https://dashboard.stripe.com
|
||||
# -----------------------------------------------------------------------------
|
||||
STRIPE_SECRET_KEY=""
|
||||
STRIPE_WEBHOOK_SECRET=""
|
||||
@ -67,33 +71,127 @@ NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY=""
|
||||
NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY=""
|
||||
# Lifetime plan - one-time payment
|
||||
NEXT_PUBLIC_STRIPE_PRICE_LIFETIME=""
|
||||
# Credit package - basic
|
||||
NEXT_PUBLIC_STRIPE_PRICE_CREDITS_BASIC=""
|
||||
# Credit package - standard
|
||||
NEXT_PUBLIC_STRIPE_PRICE_CREDITS_STANDARD=""
|
||||
# Credit package - premium
|
||||
NEXT_PUBLIC_STRIPE_PRICE_CREDITS_PREMIUM=""
|
||||
# Credit package - enterprise
|
||||
NEXT_PUBLIC_STRIPE_PRICE_CREDITS_ENTERPRISE=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Analytics
|
||||
# Configurations
|
||||
# -----------------------------------------------------------------------------
|
||||
# Disable image optimization, check out next.config.ts for more details
|
||||
# -----------------------------------------------------------------------------
|
||||
DISABLE_IMAGE_OPTIMIZATION=false
|
||||
# -----------------------------------------------------------------------------
|
||||
# Run this website as demo website, in most cases, you should set this to false
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_DEMO_WEBSITE=false
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Analytics
|
||||
# https://mksaas.com/docs/analytics
|
||||
# -----------------------------------------------------------------------------
|
||||
# Google Analytics (https://analytics.google.com)
|
||||
# https://mksaas.com/docs/analytics#google
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# Umami Analytics (https://umami.is)
|
||||
# https://mksaas.com/docs/analytics#umami
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=""
|
||||
NEXT_PUBLIC_UMAMI_SCRIPT="https://cloud.umami.is/script.js"
|
||||
# -----------------------------------------------------------------------------
|
||||
# OpenPanel Analytics (https://openpanel.dev)
|
||||
# https://mksaas.com/docs/analytics#openpanel
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_OPENPANEL_CLIENT_ID=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# Plausible Analytics (https://plausible.io)
|
||||
# https://mksaas.com/docs/analytics#plausible
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=""
|
||||
NEXT_PUBLIC_PLAUSIBLE_SCRIPT="https://plausible.io/js/script.js"
|
||||
# -----------------------------------------------------------------------------
|
||||
# Ahrefs Analytics (https://ahrefs.com)
|
||||
# https://mksaas.com/docs/analytics#ahrefs
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_AHREFS_WEBSITE_ID=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# Seline Analytics
|
||||
# https://mksaas.com/docs/analytics#seline
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_SELINE_TOKEN=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# DataFast Analytics (https://datafa.st)
|
||||
# https://mksaas.com/docs/analytics#datafast
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_DATAFAST_ANALYTICS_ID=""
|
||||
NEXT_PUBLIC_DATAFAST_ANALYTICS_DOMAIN=""
|
||||
NEXT_PUBLIC_DATAFAST_WEBSITE_ID=""
|
||||
NEXT_PUBLIC_DATAFAST_DOMAIN=""
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Notification (Discord)
|
||||
# -----------------------------------------------------------------------------
|
||||
DISCORD_WEBHOOK_URL=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# Notification (Feishu)
|
||||
# -----------------------------------------------------------------------------
|
||||
FEISHU_WEBHOOK_URL=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Affiliate
|
||||
# https://mksaas.com/docs/affiliate
|
||||
# -----------------------------------------------------------------------------
|
||||
# Affonso
|
||||
# https://affonso.com/
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_AFFILIATE_AFFONSO_ID=""
|
||||
# -----------------------------------------------------------------------------
|
||||
# PromoteKit
|
||||
# https://www.promotekit.com/
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_AFFILIATE_PROMOTEKIT_ID=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Captcha (Cloudflare Turnstile)
|
||||
# https://mksaas.com/docs/captcha
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
|
||||
TURNSTILE_SECRET_KEY=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Crisp
|
||||
# https://mksaas.com/docs/chat
|
||||
# -----------------------------------------------------------------------------
|
||||
NEXT_PUBLIC_CRISP_WEBSITE_ID=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Cron Jobs
|
||||
# https://mksaas.com/docs/cronjobs
|
||||
# -----------------------------------------------------------------------------
|
||||
CRON_JOBS_USERNAME=""
|
||||
CRON_JOBS_PASSWORD=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# AI
|
||||
# https://mksaas.com/docs/ai
|
||||
# -----------------------------------------------------------------------------
|
||||
AI_GATEWAY_API_KEY=""
|
||||
FAL_API_KEY=""
|
||||
FIREWORKS_API_KEY=""
|
||||
OPENAI_API_KEY=""
|
||||
REPLICATE_API_TOKEN=""
|
||||
GOOGLE_GENERATIVE_AI_API_KEY=""
|
||||
DEEPSEEK_API_KEY=""
|
||||
OPENROUTER_API_KEY=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Web Content Analyzer (Firecrawl)
|
||||
# https://firecrawl.dev/
|
||||
# -----------------------------------------------------------------------------
|
||||
FIRECRAWL_API_KEY=""
|
||||
|
287
messages/en.json
@ -1,10 +1,11 @@
|
||||
{
|
||||
"Metadata": {
|
||||
"name": "MkSaaS",
|
||||
"name": "MkSaaS Demo",
|
||||
"title": "MkSaaS - The Best AI SaaS Boilerplate",
|
||||
"description": "MkSaaS is the best AI SaaS boilerplate. Make AI SaaS in days, simply and effortlessly"
|
||||
},
|
||||
"Common": {
|
||||
"premium": "Premium",
|
||||
"login": "Log in",
|
||||
"logout": "Log out",
|
||||
"signUp": "Sign up",
|
||||
@ -28,7 +29,21 @@
|
||||
"save": "Save",
|
||||
"loading": "Loading...",
|
||||
"cancel": "Cancel",
|
||||
"logoutFailed": "Failed to log out"
|
||||
"logoutFailed": "Failed to log out",
|
||||
"table": {
|
||||
"totalRecords": "Total {count} records",
|
||||
"noResults": "No results",
|
||||
"loading": "Loading...",
|
||||
"columns": "Columns",
|
||||
"rowsPerPage": "Rows per page",
|
||||
"page": "Page",
|
||||
"firstPage": "First Page",
|
||||
"lastPage": "Last Page",
|
||||
"nextPage": "Next Page",
|
||||
"previousPage": "Previous Page",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc"
|
||||
}
|
||||
},
|
||||
"PricingPage": {
|
||||
"title": "Pricing",
|
||||
@ -99,6 +114,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreditPackages": {
|
||||
"basic": {
|
||||
"name": "Basic",
|
||||
"description": "Basic credits package description"
|
||||
},
|
||||
"standard": {
|
||||
"name": "Standard",
|
||||
"description": "Standard credits package description"
|
||||
},
|
||||
"premium": {
|
||||
"name": "Premium",
|
||||
"description": "Premium credits package description"
|
||||
},
|
||||
"enterprise": {
|
||||
"name": "Enterprise",
|
||||
"description": "Enterprise credits package description"
|
||||
}
|
||||
},
|
||||
"NotFoundPage": {
|
||||
"title": "404",
|
||||
"message": "Sorry, the page you are looking for does not exist.",
|
||||
@ -112,11 +145,11 @@
|
||||
"AboutPage": {
|
||||
"title": "About",
|
||||
"description": "This is MkSaaS, an AI SaaS template built with modern technologies, helping you build your SaaS faster and better.",
|
||||
"subtitle": "Learn more about our company, mission, and values",
|
||||
"authorName": "MkSaaS",
|
||||
"authorBio": "AI SaaS Boilerplate",
|
||||
"introduction": "👋 Hi there! This is MkSaaS, an AI SaaS template built with modern technologies, helping you build your SaaS faster and better. If you have any questions, welcome to contact me.",
|
||||
"talkWithMe": "Talk with me"
|
||||
"talkWithMe": "Talk with me",
|
||||
"followMe": "Follow me on X"
|
||||
},
|
||||
"ChangelogPage": {
|
||||
"title": "Changelog",
|
||||
@ -160,7 +193,8 @@
|
||||
}
|
||||
},
|
||||
"Newsletter": {
|
||||
"title": "Join the community",
|
||||
"title": "Newsletter",
|
||||
"subtitle": "Join the community",
|
||||
"description": "Subscribe to our newsletter for the latest news and updates",
|
||||
"form": {
|
||||
"email": "Email",
|
||||
@ -186,7 +220,9 @@
|
||||
"hidePassword": "Hide password",
|
||||
"or": "Or continue with",
|
||||
"emailRequired": "Please enter your email",
|
||||
"passwordRequired": "Please enter your password"
|
||||
"passwordRequired": "Please enter your password",
|
||||
"captchaInvalid": "Captcha verification failed",
|
||||
"captchaError": "Captcha verification error"
|
||||
},
|
||||
"register": {
|
||||
"title": "Register",
|
||||
@ -201,7 +237,9 @@
|
||||
"hidePassword": "Hide password",
|
||||
"nameRequired": "Please enter your name",
|
||||
"emailRequired": "Please enter your email",
|
||||
"passwordRequired": "Please enter your password"
|
||||
"passwordRequired": "Please enter your password",
|
||||
"captchaInvalid": "Captcha verification failed",
|
||||
"captchaError": "Captcha verification error"
|
||||
},
|
||||
"forgotPassword": {
|
||||
"title": "Forgot Password",
|
||||
@ -255,8 +293,20 @@
|
||||
"nextPage": "Next",
|
||||
"chooseLanguage": "Select language",
|
||||
"title": "MkSaaS Docs",
|
||||
"homepage": "Homepage",
|
||||
"blog": "Blog"
|
||||
"homepage": "Homepage"
|
||||
},
|
||||
"PremiumContent": {
|
||||
"title": "Unlock Premium Content",
|
||||
"description": "Subscribe to our Pro plan to access all premium content and exclusive content.",
|
||||
"upgradeCta": "Upgrade Now",
|
||||
"benefit1": "All premium content",
|
||||
"benefit2": "Exclusive content",
|
||||
"benefit3": "Cancel anytime",
|
||||
"signIn": "Sign In",
|
||||
"loginRequired": "Sign in to continue reading",
|
||||
"loginDescription": "This is premium content. Sign in to your account to access the full content.",
|
||||
"checkingAccess": "Checking access...",
|
||||
"loadingContent": "Loading full content..."
|
||||
},
|
||||
"Marketing": {
|
||||
"navbar": {
|
||||
@ -283,6 +333,10 @@
|
||||
"title": "AI Image",
|
||||
"description": "Show how to use AI to generate beautiful images"
|
||||
},
|
||||
"chat": {
|
||||
"title": "AI Chat",
|
||||
"description": "Show how to use AI to chat with your customers"
|
||||
},
|
||||
"video": {
|
||||
"title": "AI Video",
|
||||
"description": "Show how to use AI to generate amazing videos"
|
||||
@ -333,6 +387,9 @@
|
||||
"blocks": {
|
||||
"title": "Blocks",
|
||||
"items": {
|
||||
"magicui": {
|
||||
"title": "MagicUI Blocks"
|
||||
},
|
||||
"hero-section": {
|
||||
"title": "Hero Blocks"
|
||||
},
|
||||
@ -401,6 +458,7 @@
|
||||
"title": "Resources",
|
||||
"items": {
|
||||
"blog": "Blog",
|
||||
"docs": "Documentation",
|
||||
"changelog": "Changelog",
|
||||
"roadmap": "Roadmap"
|
||||
}
|
||||
@ -425,6 +483,7 @@
|
||||
"avatar": {
|
||||
"dashboard": "Dashboard",
|
||||
"billing": "Billing",
|
||||
"credits": "Credits",
|
||||
"settings": "Settings"
|
||||
}
|
||||
},
|
||||
@ -435,7 +494,49 @@
|
||||
"admin": {
|
||||
"title": "Admin",
|
||||
"users": {
|
||||
"title": "Users"
|
||||
"title": "Users",
|
||||
"fakeData": "Note: Faked data for demonstration, some features are disabled",
|
||||
"error": "Failed to get users",
|
||||
"search": "Search users...",
|
||||
"columns": {
|
||||
"columns": "Columns",
|
||||
"name": "Name",
|
||||
"email": "Email",
|
||||
"role": "Role",
|
||||
"createdAt": "Created At",
|
||||
"customerId": "Customer ID",
|
||||
"status": "Status",
|
||||
"banReason": "Ban Reason",
|
||||
"banExpires": "Ban Expires"
|
||||
},
|
||||
"admin": "Admin",
|
||||
"user": "User",
|
||||
"email": {
|
||||
"verified": "Email Verified",
|
||||
"unverified": "Email Unverified"
|
||||
},
|
||||
"emailCopied": "Email copied to clipboard",
|
||||
"banned": "Banned",
|
||||
"active": "Active",
|
||||
"joined": "Joined at",
|
||||
"updated": "Updated at",
|
||||
"ban": {
|
||||
"reason": "Ban Reason",
|
||||
"reasonPlaceholder": "Enter the reason for banning this user",
|
||||
"defaultReason": "Spamming",
|
||||
"never": "Never",
|
||||
"expires": "Ban Expires",
|
||||
"selectDate": "Select Date",
|
||||
"button": "Ban User",
|
||||
"success": "User has been banned",
|
||||
"error": "Failed to ban user"
|
||||
},
|
||||
"unban": {
|
||||
"button": "Unban User",
|
||||
"success": "User has been unbanned",
|
||||
"error": "Failed to unban user"
|
||||
},
|
||||
"close": "Close"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@ -489,7 +590,8 @@
|
||||
"createCustomerPortalFailed": "Failed to open Stripe customer portal"
|
||||
},
|
||||
"price": "Price:",
|
||||
"nextBillingDate": "Next billing date:",
|
||||
"periodStartDate": "Period start date:",
|
||||
"periodEndDate": "Period end date:",
|
||||
"trialEnds": "Trial ends:",
|
||||
"freePlanMessage": "You are currently on the free plan with limited features",
|
||||
"lifetimeMessage": "You have lifetime access to all premium features",
|
||||
@ -497,7 +599,77 @@
|
||||
"manageBilling": "Manage Billing",
|
||||
"upgradePlan": "Upgrade Plan",
|
||||
"retry": "Retry",
|
||||
"errorMessage": "Failed to get data"
|
||||
"errorMessage": "Failed to get data",
|
||||
"paymentSuccess": "Payment successful"
|
||||
},
|
||||
"credits": {
|
||||
"title": "Credits",
|
||||
"description": "Manage your credit transactions",
|
||||
"tabs": {
|
||||
"balance": "Balance",
|
||||
"transactions": "Transactions"
|
||||
},
|
||||
"balance": {
|
||||
"title": "Credit Balance",
|
||||
"description": "Your credit balance",
|
||||
"credits": "Credits",
|
||||
"creditsDescription": "You have {credits} credits",
|
||||
"creditsExpired": "Credits expired",
|
||||
"creditsAdded": "Credits have been added to your account",
|
||||
"viewTransactions": "View Credit Transactions",
|
||||
"retry": "Retry",
|
||||
"expiringCredits": "{credits} credits expiring in the next {days} days"
|
||||
},
|
||||
"packages": {
|
||||
"title": "Credit Packages",
|
||||
"description": "Purchase additional credits to use our services",
|
||||
"purchase": "Purchase",
|
||||
"processing": "Processing...",
|
||||
"popular": "Popular",
|
||||
"completePurchase": "Complete Your Purchase",
|
||||
"failedToFetchCredits": "Failed to fetch credits",
|
||||
"failedToCreatePaymentIntent": "Failed to create payment intent",
|
||||
"failedToInitiatePayment": "Failed to initiate payment",
|
||||
"cancel": "Cancel",
|
||||
"purchaseFailed": "Purchase credits failed",
|
||||
"checkoutFailed": "Failed to create checkout session",
|
||||
"loading": "Loading...",
|
||||
"pay": "Pay"
|
||||
},
|
||||
"transactions": {
|
||||
"title": "Credit Transactions",
|
||||
"error": "Failed to get credit transactions",
|
||||
"search": "Search credit transactions...",
|
||||
"paymentIdCopied": "Payment ID copied to clipboard",
|
||||
"columns": {
|
||||
"columns": "Columns",
|
||||
"id": "ID",
|
||||
"type": "Type",
|
||||
"description": "Description",
|
||||
"amount": "Amount",
|
||||
"remainingAmount": "Remaining Amount",
|
||||
"paymentId": "Payment ID",
|
||||
"expirationDate": "Expiration Date",
|
||||
"expirationDateProcessedAt": "Expiration Date Processed At",
|
||||
"createdAt": "Created At",
|
||||
"updatedAt": "Updated At"
|
||||
},
|
||||
"types": {
|
||||
"MONTHLY_REFRESH": "Monthly Refresh",
|
||||
"REGISTER_GIFT": "Register Gift",
|
||||
"PURCHASE": "Purchased Credits",
|
||||
"USAGE": "Consumed Credits",
|
||||
"EXPIRE": "Expired Credits",
|
||||
"SUBSCRIPTION_RENEWAL": "Subscription Renewal",
|
||||
"LIFETIME_MONTHLY": "Lifetime Monthly"
|
||||
},
|
||||
"detailViewer": {
|
||||
"title": "Credit Transaction Detail",
|
||||
"close": "Close"
|
||||
},
|
||||
"expired": "Expired",
|
||||
"never": "Never"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"title": "Notification",
|
||||
@ -602,7 +774,8 @@
|
||||
"title": "Your favorite companies are our partners"
|
||||
},
|
||||
"integration": {
|
||||
"title": "Integrate with your favorite tools",
|
||||
"title": "Integrations",
|
||||
"subtitle": "Integrate with your favorite tools",
|
||||
"description": "Connect seamlessly with popular platforms and services to enhance your workflow.",
|
||||
"learnMore": "Learn More",
|
||||
"items": {
|
||||
@ -639,7 +812,8 @@
|
||||
"secondaryButton": "See Demo"
|
||||
},
|
||||
"features": {
|
||||
"title": "The features of your product",
|
||||
"title": "Features",
|
||||
"subtitle": "The features of your product",
|
||||
"description": "Write the description of your product here",
|
||||
"items": {
|
||||
"item-1": {
|
||||
@ -660,16 +834,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"features3": {
|
||||
"title": "Product Features",
|
||||
"description": "Write the description of your product here, make it as detailed as possible",
|
||||
"features2": {
|
||||
"title": "Features2",
|
||||
"subtitle": "The features of your product",
|
||||
"description": "Write the description of your product here",
|
||||
"feature-1": "Product Feature One",
|
||||
"feature-2": "Product Feature Two",
|
||||
"feature-3": "Product Feature Three",
|
||||
"feature-4": "Product Feature Four"
|
||||
},
|
||||
"features5": {
|
||||
"title": "The features of your product",
|
||||
"features3": {
|
||||
"title": "Features3",
|
||||
"subtitle": "The features of your product",
|
||||
"description": "Write the description of your product here",
|
||||
"items": {
|
||||
"item-1": {
|
||||
@ -700,11 +876,12 @@
|
||||
},
|
||||
"pricing": {
|
||||
"title": "Pricing",
|
||||
"subtitle": "Pricing",
|
||||
"description": "Choose the plan that works best for you"
|
||||
},
|
||||
"faqs": {
|
||||
"title": "Frequently Asked Questions",
|
||||
"description": "Please feel free to contact us if you have any questions",
|
||||
"title": "FAQ",
|
||||
"subtitle": "Frequently Asked Questions",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"question": "Do you offer a free trial?",
|
||||
@ -730,7 +907,7 @@
|
||||
},
|
||||
"testimonials": {
|
||||
"title": "Testimonials",
|
||||
"description": "What our customers say about us",
|
||||
"subtitle": "What our customers are saying",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"name": "Jonathan Yombo",
|
||||
@ -807,7 +984,8 @@
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "MkSaaS in numbers",
|
||||
"title": "Stats",
|
||||
"subtitle": "MkSaaS in numbers",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly",
|
||||
"items": {
|
||||
"item-1": {
|
||||
@ -829,23 +1007,68 @@
|
||||
}
|
||||
},
|
||||
"AITextPage": {
|
||||
"title": "AI Text",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly",
|
||||
"content": "Working in progress"
|
||||
"title": "AI Text Demo",
|
||||
"description": "Analyze web content with AI to extract key information, features, and insights",
|
||||
"content": "Web Content Analyzer",
|
||||
"subtitle": "Enter a website URL to get AI-powered analysis of its content",
|
||||
"analyzer": {
|
||||
"title": "Web Content Analyzer",
|
||||
"description": "Analyze any website content using AI to extract structured information",
|
||||
"placeholder": "Enter website URL (e.g., https://example.com)",
|
||||
"button": "Analyze Website",
|
||||
"loading": {
|
||||
"scraping": "Scraping website content...",
|
||||
"analyzing": "Analyzing content with AI..."
|
||||
},
|
||||
"results": {
|
||||
"title": "Analysis Results",
|
||||
"newAnalysis": "Analyze Another Website",
|
||||
"sections": {
|
||||
"title": "Title",
|
||||
"description": "Description",
|
||||
"introduction": "Introduction",
|
||||
"features": "Features",
|
||||
"pricing": "Pricing",
|
||||
"useCases": "Use Cases",
|
||||
"screenshot": "Website Screenshot"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"invalidUrl": "Please enter a valid URL starting with http:// or https://",
|
||||
"analysisError": "Failed to analyze website. Please try again.",
|
||||
"networkError": "Network error. Please check your connection and try again.",
|
||||
"insufficientCredits": "Insufficient credits. Please purchase more credits to continue."
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"scraping": {
|
||||
"title": "Smart Web Scraping",
|
||||
"description": "Advanced web scraping technology extracts clean, structured content from any website"
|
||||
},
|
||||
"analysis": {
|
||||
"title": "AI-Powered Analysis",
|
||||
"description": "Intelligent AI analysis extracts key insights, features, and structured information"
|
||||
},
|
||||
"results": {
|
||||
"title": "Structured Results",
|
||||
"description": "Get organized, easy-to-read results with clear sections and actionable insights"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AIImagePage": {
|
||||
"title": "AI Image",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly",
|
||||
"content": "Working in progress"
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly"
|
||||
},
|
||||
"AIChatPage": {
|
||||
"title": "AI Chat",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly"
|
||||
},
|
||||
"AIVideoPage": {
|
||||
"title": "AI Video",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly",
|
||||
"content": "Working in progress"
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly"
|
||||
},
|
||||
"AIAudioPage": {
|
||||
"title": "AI Audio",
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly",
|
||||
"content": "Working in progress"
|
||||
"description": "MkSaaS lets you make AI SaaS in days, simply and effortlessly"
|
||||
}
|
||||
}
|
||||
|
312
messages/zh.json
@ -1,10 +1,11 @@
|
||||
{
|
||||
"Metadata": {
|
||||
"name": "MkSaaS",
|
||||
"name": "MkSaaS Demo",
|
||||
"title": "MkSaaS - 最好的 AI SaaS 模板",
|
||||
"description": "MkSaaS 是构建 AI SaaS 的最佳模板,使用 MkSaaS 可以在几天内轻松构建您的 AI SaaS,简单且毫不费力。"
|
||||
},
|
||||
"Common": {
|
||||
"premium": "付费文章",
|
||||
"login": "登录",
|
||||
"logout": "退出",
|
||||
"signUp": "注册",
|
||||
@ -28,7 +29,21 @@
|
||||
"saving": "保存中...",
|
||||
"loading": "加载中...",
|
||||
"cancel": "取消",
|
||||
"logoutFailed": "退出失败"
|
||||
"logoutFailed": "退出失败",
|
||||
"table": {
|
||||
"totalRecords": "总共 {count} 条记录",
|
||||
"noResults": "无结果",
|
||||
"loading": "加载中...",
|
||||
"columns": "列",
|
||||
"rowsPerPage": "每页行数",
|
||||
"page": "页",
|
||||
"firstPage": "第一页",
|
||||
"lastPage": "最后一页",
|
||||
"nextPage": "下一页",
|
||||
"previousPage": "上一页",
|
||||
"ascending": "升序",
|
||||
"descending": "降序"
|
||||
}
|
||||
},
|
||||
"PricingPage": {
|
||||
"title": "价格",
|
||||
@ -94,12 +109,29 @@
|
||||
"feature-3": "专属支持",
|
||||
"feature-4": "企业级安全",
|
||||
"feature-5": "高级集成",
|
||||
"feature-6": "自定义域名",
|
||||
"feature-7": "自定义品牌",
|
||||
"feature-8": "终身更新"
|
||||
"feature-6": "自定义品牌",
|
||||
"feature-7": "终身更新"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreditPackages": {
|
||||
"basic": {
|
||||
"name": "基础版",
|
||||
"description": "基础版功能介绍放这里"
|
||||
},
|
||||
"standard": {
|
||||
"name": "标准版",
|
||||
"description": "标准版功能介绍放这里"
|
||||
},
|
||||
"premium": {
|
||||
"name": "高级版",
|
||||
"description": "高级版功能介绍放这里"
|
||||
},
|
||||
"enterprise": {
|
||||
"name": "企业版",
|
||||
"description": "企业版功能介绍放这里"
|
||||
}
|
||||
},
|
||||
"NotFoundPage": {
|
||||
"title": "404",
|
||||
"message": "抱歉,您正在寻找的页面不存在",
|
||||
@ -113,11 +145,11 @@
|
||||
"AboutPage": {
|
||||
"title": "关于我们",
|
||||
"description": "MkSaaS 是一个使用最先进的技术栈构建的 AI SaaS 模板,它可以帮助你更快更好地构建你的 SaaS。如果你有任何问题,欢迎联系我。",
|
||||
"subtitle": "了解更多关于我们的公司、使命和价值观",
|
||||
"authorName": "MkSaaS",
|
||||
"authorBio": "最好的 AI SaaS 模板",
|
||||
"introduction": "👋 你好,这里是 MkSaaS,一个使用最先进的技术栈构建的 AI SaaS 模板,它可以帮助你更快更好地构建你的 SaaS。如果你有任何问题,欢迎联系我。",
|
||||
"talkWithMe": "联系我"
|
||||
"talkWithMe": "联系我",
|
||||
"followMe": "关注我"
|
||||
},
|
||||
"ChangelogPage": {
|
||||
"title": "更新日志",
|
||||
@ -161,7 +193,8 @@
|
||||
}
|
||||
},
|
||||
"Newsletter": {
|
||||
"title": "加入我们的社区",
|
||||
"title": "邮件列表",
|
||||
"subtitle": "加入我们的社区",
|
||||
"description": "订阅邮件列表,及时获取最新消息和更新",
|
||||
"form": {
|
||||
"email": "邮箱",
|
||||
@ -187,7 +220,9 @@
|
||||
"hidePassword": "隐藏密码",
|
||||
"or": "或以社媒账号登录",
|
||||
"emailRequired": "请输入邮箱",
|
||||
"passwordRequired": "请输入密码"
|
||||
"passwordRequired": "请输入密码",
|
||||
"captchaInvalid": "验证码验证失败",
|
||||
"captchaError": "验证码验证出错"
|
||||
},
|
||||
"register": {
|
||||
"title": "注册",
|
||||
@ -202,7 +237,9 @@
|
||||
"hidePassword": "隐藏密码",
|
||||
"nameRequired": "请输入姓名",
|
||||
"emailRequired": "请输入邮箱",
|
||||
"passwordRequired": "请输入密码"
|
||||
"passwordRequired": "请输入密码",
|
||||
"captchaInvalid": "验证码验证失败",
|
||||
"captchaError": "验证码验证出错"
|
||||
},
|
||||
"forgotPassword": {
|
||||
"title": "忘记密码",
|
||||
@ -256,8 +293,20 @@
|
||||
"nextPage": "下一页",
|
||||
"chooseLanguage": "选择语言",
|
||||
"title": "MkSaaS文档",
|
||||
"homepage": "首页",
|
||||
"blog": "博客"
|
||||
"homepage": "首页"
|
||||
},
|
||||
"PremiumContent": {
|
||||
"title": "解锁付费内容",
|
||||
"description": "订阅我们的付费计划,访问所有付费内容和独家内容。",
|
||||
"upgradeCta": "立即升级",
|
||||
"benefit1": "所有内容",
|
||||
"benefit2": "独家内容",
|
||||
"benefit3": "随时取消",
|
||||
"signIn": "登录",
|
||||
"loginRequired": "登录以继续阅读",
|
||||
"loginDescription": "这是一篇付费内容,请登录您的账户以访问完整内容。",
|
||||
"checkingAccess": "检查阅读权限...",
|
||||
"loadingContent": "加载完整内容..."
|
||||
},
|
||||
"Marketing": {
|
||||
"navbar": {
|
||||
@ -284,6 +333,10 @@
|
||||
"title": "AI 图像",
|
||||
"description": "展示如何使用 AI 生成精美图像"
|
||||
},
|
||||
"chat": {
|
||||
"title": "AI 聊天",
|
||||
"description": "展示如何使用 AI 与客户聊天"
|
||||
},
|
||||
"video": {
|
||||
"title": "AI 视频",
|
||||
"description": "展示如何使用 AI 生成惊人视频"
|
||||
@ -334,6 +387,9 @@
|
||||
"blocks": {
|
||||
"title": "内置组件",
|
||||
"items": {
|
||||
"magicui": {
|
||||
"title": "MagicUI 组件"
|
||||
},
|
||||
"hero-section": {
|
||||
"title": "Hero 组件"
|
||||
},
|
||||
@ -370,13 +426,13 @@
|
||||
"comparator": {
|
||||
"title": "Comparator 组件"
|
||||
},
|
||||
"faqs": {
|
||||
"title": "FAQs 组件"
|
||||
"faq": {
|
||||
"title": "FAQ 组件"
|
||||
},
|
||||
"login": {
|
||||
"title": "Login 组件"
|
||||
},
|
||||
"sign-up": {
|
||||
"signup": {
|
||||
"title": "Signup 组件"
|
||||
},
|
||||
"forgot-password": {
|
||||
@ -402,6 +458,7 @@
|
||||
"title": "资源",
|
||||
"items": {
|
||||
"blog": "博客",
|
||||
"docs": "文档",
|
||||
"changelog": "更新日志",
|
||||
"roadmap": "路线图"
|
||||
}
|
||||
@ -426,6 +483,7 @@
|
||||
"avatar": {
|
||||
"dashboard": "工作台",
|
||||
"billing": "账单",
|
||||
"credits": "积分",
|
||||
"settings": "设置"
|
||||
}
|
||||
},
|
||||
@ -436,7 +494,49 @@
|
||||
"admin": {
|
||||
"title": "系统管理",
|
||||
"users": {
|
||||
"title": "用户管理"
|
||||
"title": "用户管理",
|
||||
"fakeData": "注:只为演示功能,数据为假数据,封禁功能不可用",
|
||||
"error": "获取用户失败",
|
||||
"search": "搜索用户...",
|
||||
"columns": {
|
||||
"columns": "显示列",
|
||||
"name": "姓名",
|
||||
"email": "邮箱",
|
||||
"role": "角色",
|
||||
"createdAt": "创建时间",
|
||||
"customerId": "客户ID",
|
||||
"status": "状态",
|
||||
"banReason": "封禁原因",
|
||||
"banExpires": "封禁到期时间"
|
||||
},
|
||||
"admin": "管理员",
|
||||
"user": "用户",
|
||||
"email": {
|
||||
"verified": "邮箱已验证",
|
||||
"unverified": "邮箱未验证"
|
||||
},
|
||||
"emailCopied": "邮箱已复制到剪贴板",
|
||||
"banned": "账号被封禁",
|
||||
"active": "账号正常",
|
||||
"joined": "加入时间",
|
||||
"updated": "更新时间",
|
||||
"ban": {
|
||||
"reason": "封禁原因",
|
||||
"reasonPlaceholder": "请输入封禁该用户的原因",
|
||||
"defaultReason": "垃圾信息",
|
||||
"never": "永不解禁",
|
||||
"expires": "封禁到期时间",
|
||||
"selectDate": "选择日期",
|
||||
"button": "封禁用户",
|
||||
"success": "用户已被封禁",
|
||||
"error": "封禁用户失败"
|
||||
},
|
||||
"unban": {
|
||||
"button": "解除封禁",
|
||||
"success": "用户已被解除封禁",
|
||||
"error": "解除封禁失败"
|
||||
},
|
||||
"close": "关闭"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@ -490,7 +590,8 @@
|
||||
"createCustomerPortalFailed": "打开Stripe客户界面失败"
|
||||
},
|
||||
"price": "价格:",
|
||||
"nextBillingDate": "下次账单日期:",
|
||||
"periodStartDate": "周期开始日期:",
|
||||
"periodEndDate": "周期结束日期:",
|
||||
"trialEnds": "试用结束日期:",
|
||||
"freePlanMessage": "您当前使用的是功能有限的免费方案",
|
||||
"lifetimeMessage": "您拥有所有高级功能的终身使用权限",
|
||||
@ -498,7 +599,77 @@
|
||||
"manageBilling": "管理账单",
|
||||
"upgradePlan": "升级方案",
|
||||
"retry": "重试",
|
||||
"errorMessage": "获取数据失败"
|
||||
"errorMessage": "获取数据失败",
|
||||
"paymentSuccess": "支付成功"
|
||||
},
|
||||
"credits": {
|
||||
"title": "积分",
|
||||
"description": "管理您的积分交易",
|
||||
"tabs": {
|
||||
"balance": "积分余额",
|
||||
"transactions": "交易记录"
|
||||
},
|
||||
"balance": {
|
||||
"title": "积分余额",
|
||||
"description": "您的积分余额",
|
||||
"credits": "积分",
|
||||
"creditsDescription": "您有 {credits} 积分",
|
||||
"creditsExpired": "积分已过期",
|
||||
"creditsAdded": "积分已添加到您的账户",
|
||||
"viewTransactions": "查看积分记录",
|
||||
"retry": "重试",
|
||||
"expiringCredits": "{credits} 积分将在 {days} 天内过期"
|
||||
},
|
||||
"packages": {
|
||||
"title": "积分套餐",
|
||||
"description": "购买积分以使用我们的更多服务",
|
||||
"purchase": "购买",
|
||||
"processing": "处理中...",
|
||||
"popular": "热门",
|
||||
"completePurchase": "请支付订单",
|
||||
"failedToFetchCredits": "获取积分失败",
|
||||
"failedToCreatePaymentIntent": "创建付款意向失败",
|
||||
"failedToInitiatePayment": "发起付款失败",
|
||||
"cancel": "取消",
|
||||
"purchaseFailed": "购买积分失败",
|
||||
"checkoutFailed": "创建支付会话失败",
|
||||
"loading": "加载中...",
|
||||
"pay": "支付"
|
||||
},
|
||||
"transactions": {
|
||||
"title": "积分记录",
|
||||
"error": "获取积分交易记录失败",
|
||||
"search": "搜索积分交易记录...",
|
||||
"paymentIdCopied": "支付ID已复制到剪贴板",
|
||||
"columns": {
|
||||
"columns": "列",
|
||||
"id": "ID",
|
||||
"type": "类型",
|
||||
"description": "描述",
|
||||
"amount": "金额",
|
||||
"remainingAmount": "剩余金额",
|
||||
"paymentId": "支付编号",
|
||||
"expirationDate": "过期日期",
|
||||
"expirationDateProcessedAt": "过期处理时间",
|
||||
"createdAt": "创建时间",
|
||||
"updatedAt": "更新时间"
|
||||
},
|
||||
"types": {
|
||||
"MONTHLY_REFRESH": "每月赠送",
|
||||
"REGISTER_GIFT": "注册赠送",
|
||||
"PURCHASE": "购买积分",
|
||||
"USAGE": "使用积分",
|
||||
"EXPIRE": "过期积分",
|
||||
"SUBSCRIPTION_RENEWAL": "订阅月度积分",
|
||||
"LIFETIME_MONTHLY": "终身月度积分"
|
||||
},
|
||||
"detailViewer": {
|
||||
"title": "积分交易详情",
|
||||
"close": "关闭"
|
||||
},
|
||||
"expired": "已过期",
|
||||
"never": "永不过期"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"title": "通知",
|
||||
@ -591,9 +762,9 @@
|
||||
},
|
||||
"HomePage": {
|
||||
"title": "MkSaaS",
|
||||
"description": "使用 MkSaaS 在几天内轻松构建您的 AI SaaS",
|
||||
"description": "使用 MkSaaS 在几天内轻松构建您的 AI SaaS 产品",
|
||||
"hero": {
|
||||
"title": "使用 MkSaaS 轻松构建您的 AI SaaS",
|
||||
"title": "使用 MkSaaS 轻松构建您的 AI SaaS 产品",
|
||||
"description": "MkSaaS 是构建 AI SaaS 的最佳模板,内置 AI、身份验证、全球支付、博客、文档、邮件订阅、SEO、多彩主题、丰富组件等。",
|
||||
"introduction": "介绍 MkSaaS 模板",
|
||||
"primary": "开始使用",
|
||||
@ -603,7 +774,8 @@
|
||||
"title": "您最爱公司都是我们的合作伙伴"
|
||||
},
|
||||
"integration": {
|
||||
"title": "与您最喜欢的工具集成",
|
||||
"title": "集成",
|
||||
"subtitle": "与您最喜欢的工具集成",
|
||||
"description": "无缝连接流行的平台和服务,以增强您的工作流程。",
|
||||
"learnMore": "了解更多",
|
||||
"items": {
|
||||
@ -640,8 +812,9 @@
|
||||
"secondaryButton": "查看演示"
|
||||
},
|
||||
"features": {
|
||||
"title": "您的 SaaS 产品功能",
|
||||
"description": "请在详细介绍您的 SaaS 产品的特色功能的信息",
|
||||
"title": "功能",
|
||||
"subtitle": "您的 SaaS 产品功能",
|
||||
"description": "请在这里介绍您的 SaaS 产品的特色功能的信息",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"title": "产品特色功能一",
|
||||
@ -661,9 +834,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"features5": {
|
||||
"title": "您的 SaaS 产品功能",
|
||||
"description": "请在详细介绍您的 SaaS 产品的特色功能的信息",
|
||||
"features2": {
|
||||
"title": "功能2",
|
||||
"subtitle": "您的 SaaS 产品功能",
|
||||
"description": "请在这里介绍您的 SaaS 产品的特色功能的信息",
|
||||
"feature-1": "特色功能特点一",
|
||||
"feature-2": "特色功能特点二",
|
||||
"feature-3": "特色功能特点三",
|
||||
"feature-4": "特色功能特点四"
|
||||
},
|
||||
"features3": {
|
||||
"title": "功能3",
|
||||
"subtitle": "您的 SaaS 产品功能",
|
||||
"description": "请在这里介绍您的 SaaS 产品的特色功能的信息",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"title": "产品特色功能一",
|
||||
@ -691,21 +874,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"features3": {
|
||||
"title": "产品特色功能",
|
||||
"description": "请在详细介绍您的 SaaS 产品的特色功能的信息,尽可能详细,使其更吸引用户,提高落地页的转化率",
|
||||
"feature-1": "特色功能特点一",
|
||||
"feature-2": "特色功能特点二",
|
||||
"feature-3": "特色功能特点三",
|
||||
"feature-4": "特色功能特点四"
|
||||
},
|
||||
"pricing": {
|
||||
"title": "价格",
|
||||
"subtitle": "价格",
|
||||
"description": "选择最适合您的付费计划"
|
||||
},
|
||||
"faqs": {
|
||||
"title": "常见问题",
|
||||
"description": "如果您有任何问题,请随时联系我们",
|
||||
"subtitle": "如果您有任何问题,请随时联系我们",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"question": "你们提供免费试用吗?",
|
||||
@ -731,7 +907,7 @@
|
||||
},
|
||||
"testimonials": {
|
||||
"title": "客户评价",
|
||||
"description": "我们的客户对我们的评价",
|
||||
"subtitle": "我们的客户对我们的评价",
|
||||
"items": {
|
||||
"item-1": {
|
||||
"name": "Jonathan Yombo",
|
||||
@ -808,7 +984,8 @@
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "MkSaaS 相关的数字",
|
||||
"title": "统计",
|
||||
"subtitle": "MkSaaS 相关的数字",
|
||||
"description": "MkSaaS 可让您在几天内轻松构建您的 AI SaaS",
|
||||
"items": {
|
||||
"item-1": {
|
||||
@ -831,22 +1008,67 @@
|
||||
},
|
||||
"AITextPage": {
|
||||
"title": "AI 文本",
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力",
|
||||
"content": "正在开发中"
|
||||
"description": "使用 AI 分析网页内容,提取关键信息、功能和见解",
|
||||
"content": "网页内容分析器",
|
||||
"subtitle": "输入网站 URL,使用 AI 分析其内容",
|
||||
"analyzer": {
|
||||
"title": "网页内容分析器",
|
||||
"description": "使用 AI 分析任何网站的内容,提取结构化信息",
|
||||
"placeholder": "输入网站 URL(例如:https://example.com)",
|
||||
"button": "分析网站",
|
||||
"loading": {
|
||||
"scraping": "正在抓取网站内容...",
|
||||
"analyzing": "正在使用 AI 分析内容..."
|
||||
},
|
||||
"results": {
|
||||
"title": "分析结果",
|
||||
"newAnalysis": "分析其他网站",
|
||||
"sections": {
|
||||
"title": "标题",
|
||||
"description": "描述",
|
||||
"introduction": "介绍",
|
||||
"features": "功能",
|
||||
"pricing": "定价",
|
||||
"useCases": "使用场景",
|
||||
"screenshot": "网站截图"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"invalidUrl": "请输入以 http:// 或 https:// 开头的有效 URL",
|
||||
"analysisError": "分析网站失败,请重试。",
|
||||
"networkError": "网络错误,请检查您的连接并重试。",
|
||||
"insufficientCredits": "积分不足,请购买更多积分以继续。"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"scraping": {
|
||||
"title": "智能网页抓取",
|
||||
"description": "先进的网页抓取技术从任何网站提取干净、结构化的内容"
|
||||
},
|
||||
"analysis": {
|
||||
"title": "AI 驱动分析",
|
||||
"description": "智能 AI 分析提取关键见解、功能和结构化信息"
|
||||
},
|
||||
"results": {
|
||||
"title": "结构化结果",
|
||||
"description": "获得有组织、易于阅读的结果,包含清晰的部分和可操作的见解"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AIImagePage": {
|
||||
"title": "AI 图片",
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力",
|
||||
"content": "正在开发中"
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力"
|
||||
},
|
||||
"AIChatPage": {
|
||||
"title": "AI 聊天",
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力"
|
||||
},
|
||||
"AIVideoPage": {
|
||||
"title": "AI 视频",
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力",
|
||||
"content": "正在开发中"
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力"
|
||||
},
|
||||
"AIAudioPage": {
|
||||
"title": "AI 音频",
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力",
|
||||
"content": "正在开发中"
|
||||
"description": "MkSaaS 让您在几天内轻松构建您的 AI SaaS,简单且毫不费力"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { withContentCollections } from '@content-collections/next';
|
||||
import { createMDX } from 'fumadocs-mdx/next';
|
||||
import type { NextConfig } from 'next';
|
||||
import createNextIntlPlugin from 'next-intl/plugin';
|
||||
|
||||
@ -6,16 +6,35 @@ import createNextIntlPlugin from 'next-intl/plugin';
|
||||
* https://nextjs.org/docs/app/api-reference/config/next-config-js
|
||||
*/
|
||||
const nextConfig: NextConfig = {
|
||||
// Docker standalone output
|
||||
...(process.env.DOCKER_BUILD === 'true' && { output: 'standalone' }),
|
||||
|
||||
/* config options here */
|
||||
devIndicators: false,
|
||||
|
||||
// https://nextjs.org/docs/architecture/nextjs-compiler#remove-console
|
||||
// Remove all console.* calls in production only
|
||||
compiler: {
|
||||
removeConsole: process.env.NODE_ENV === 'production',
|
||||
// removeConsole: process.env.NODE_ENV === 'production',
|
||||
},
|
||||
|
||||
// https://github.com/vercel/next.js/discussions/50177#discussioncomment-6006702
|
||||
// fix build error: Module build failed: UnhandledSchemeError:
|
||||
// Reading from "cloudflare:sockets" is not handled by plugins (Unhandled scheme).
|
||||
webpack: (config, { webpack }) => {
|
||||
config.plugins.push(
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /^pg-native$|^cloudflare:sockets$/,
|
||||
})
|
||||
);
|
||||
return config;
|
||||
},
|
||||
|
||||
images: {
|
||||
// https://vercel.com/docs/image-optimization/managing-image-optimization-costs#minimizing-image-optimization-costs
|
||||
// https://nextjs.org/docs/app/api-reference/components/image#unoptimized
|
||||
// vercel has limits on image optimization, 1000 images per month
|
||||
unoptimized: process.env.DISABLE_IMAGE_OPTIMIZATION === 'true',
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
@ -33,6 +52,18 @@ const nextConfig: NextConfig = {
|
||||
protocol: 'https',
|
||||
hostname: 'res.cloudinary.com',
|
||||
},
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'ik.imagekit.io',
|
||||
},
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'html.tailus.io',
|
||||
},
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'service.firecrawl.dev',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@ -45,8 +76,15 @@ const nextConfig: NextConfig = {
|
||||
const withNextIntl = createNextIntlPlugin();
|
||||
|
||||
/**
|
||||
* withContentCollections must be the outermost plugin
|
||||
*
|
||||
* https://www.content-collections.dev/docs/quickstart/next
|
||||
* https://fumadocs.dev/docs/ui/manual-installation
|
||||
* https://fumadocs.dev/docs/mdx/plugin
|
||||
*/
|
||||
export default withContentCollections(withNextIntl(nextConfig));
|
||||
const withMDX = createMDX();
|
||||
|
||||
export default withMDX(withNextIntl(nextConfig));
|
||||
|
||||
// https://opennext.js.org/cloudflare/get-started#12-develop-locally
|
||||
import { initOpenNextCloudflareForDev } from '@opennextjs/cloudflare';
|
||||
|
||||
// during local development, to access in any of your server code, local versions of Cloudflare bindings
|
||||
initOpenNextCloudflareForDev();
|
||||
|
6
open-next.config.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
|
||||
|
||||
|
||||
export default defineCloudflareConfig({
|
||||
|
||||
});
|
92
package.json
@ -3,9 +3,11 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "concurrently \"content-collections watch\" \"next dev\"",
|
||||
"build": "content-collections build && next build",
|
||||
"dev": "next dev",
|
||||
"cf-dev": "next dev -p 8787",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"postinstall": "fumadocs-mdx",
|
||||
"lint": "biome check --write .",
|
||||
"lint:fix": "biome check --fix --unsafe .",
|
||||
"format": "biome format --write .",
|
||||
@ -13,25 +15,36 @@
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:push": "drizzle-kit push",
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"docs": "content-collections build",
|
||||
"email": "email dev --dir src/mail/emails --port 3333"
|
||||
"list-contacts": "tsx scripts/list-contacts.ts",
|
||||
"list-users": "tsx scripts/list-users.ts",
|
||||
"content": "fumadocs-mdx",
|
||||
"email": "email dev --dir src/mail/templates --port 3333",
|
||||
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||
"upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
|
||||
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
|
||||
"knip": "knip"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "^1.1.13",
|
||||
"@aws-sdk/client-s3": "^3.758.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.758.0",
|
||||
"@content-collections/core": "^0.8.0",
|
||||
"@content-collections/mdx": "^0.2.0",
|
||||
"@content-collections/next": "^0.2.4",
|
||||
"@ai-sdk/deepseek": "^1.0.0",
|
||||
"@ai-sdk/fal": "^1.0.0",
|
||||
"@ai-sdk/fireworks": "^1.0.0",
|
||||
"@ai-sdk/google": "^2.0.0",
|
||||
"@ai-sdk/openai": "^2.0.0",
|
||||
"@ai-sdk/react": "^2.0.22",
|
||||
"@ai-sdk/replicate": "^1.0.0",
|
||||
"@base-ui-components/react": "1.0.0-beta.0",
|
||||
"@better-fetch/fetch": "^1.1.18",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@fumadocs/content-collections": "^1.1.8",
|
||||
"@hookform/resolvers": "^4.1.0",
|
||||
"@neondatabase/serverless": "^0.10.4",
|
||||
"@hookform/resolvers": "^5.2.1",
|
||||
"@marsidev/react-turnstile": "^1.1.0",
|
||||
"@mendable/firecrawl-js": "^1.29.1",
|
||||
"@next/third-parties": "^15.3.0",
|
||||
"@openpanel/nextjs": "^1.0.7",
|
||||
"@openrouter/ai-sdk-provider": "^1.0.0-beta.6",
|
||||
"@orama/orama": "^3.1.4",
|
||||
"@orama/tokenizers": "^3.1.4",
|
||||
"@radix-ui/react-accordion": "^1.2.3",
|
||||
@ -63,19 +76,25 @@
|
||||
"@radix-ui/react-toggle": "^1.1.2",
|
||||
"@radix-ui/react-toggle-group": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
||||
"@react-email/components": "0.0.33",
|
||||
"@react-email/render": "1.0.5",
|
||||
"@stripe/stripe-js": "^5.6.0",
|
||||
"@tabler/icons-react": "^3.31.0",
|
||||
"@tanstack/react-query": "^5.85.5",
|
||||
"@tanstack/react-query-devtools": "^5.85.5",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
"@types/canvas-confetti": "^1.9.0",
|
||||
"ai": "^4.1.45",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"@vercel/speed-insights": "^1.2.0",
|
||||
"ai": "^5.0.0",
|
||||
"better-auth": "^1.1.19",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "1.1.1",
|
||||
"cookie": "^1.0.2",
|
||||
"crisp-sdk-web": "^1.0.25",
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"dotenv": "^16.4.7",
|
||||
@ -83,62 +102,65 @@
|
||||
"drizzle-orm": "^0.39.3",
|
||||
"embla-carousel-react": "^8.5.2",
|
||||
"framer-motion": "^12.4.7",
|
||||
"fumadocs-core": "^15.1.2",
|
||||
"fumadocs-ui": "^15.1.2",
|
||||
"geist": "^1.3.1",
|
||||
"fumadocs-core": "^15.6.7",
|
||||
"fumadocs-mdx": "^11.7.3",
|
||||
"fumadocs-ui": "^15.6.7",
|
||||
"input-otp": "^1.4.2",
|
||||
"lucide-react": "^0.483.0",
|
||||
"mdast-util-toc": "^7.1.0",
|
||||
"motion": "^12.4.3",
|
||||
"next": "15.2.1",
|
||||
"next-intl": "^4.0.0",
|
||||
"next-plausible": "^3.12.4",
|
||||
"next-safe-action": "^7.10.4",
|
||||
"next-themes": "^0.4.4",
|
||||
"pg": "^8.16.0",
|
||||
"nuqs": "^2.5.1",
|
||||
"postgres": "^3.4.5",
|
||||
"radix-ui": "^1.4.2",
|
||||
"react": "^19.0.0",
|
||||
"react-day-picker": "9.6.3",
|
||||
"react-day-picker": "8.10.1",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-hook-form": "^7.62.0",
|
||||
"react-remove-scroll": "^2.6.3",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"react-syntax-highlighter": "^15.6.3",
|
||||
"react-tweet": "^3.2.2",
|
||||
"react-use-measure": "^2.1.7",
|
||||
"recharts": "^2.15.1",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-pretty-code": "^0.14.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"remark": "^15.0.1",
|
||||
"remark-code-import": "^1.2.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"resend": "^4.3.0",
|
||||
"resend": "^4.4.1",
|
||||
"s3mini": "^0.2.0",
|
||||
"shiki": "^2.4.2",
|
||||
"sonner": "^2.0.0",
|
||||
"streamdown": "^1.0.12",
|
||||
"stripe": "^17.6.0",
|
||||
"swiper": "^11.2.5",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "^1.2.4",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"use-intl": "^3.26.5",
|
||||
"use-media": "^1.5.0",
|
||||
"use-stick-to-bottom": "^1.1.1",
|
||||
"vaul": "^1.1.2",
|
||||
"zod": "^3.24.2",
|
||||
"zod": "^4.0.17",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@content-collections/cli": "^0.1.6",
|
||||
"@opennextjs/cloudflare": "^1.6.5",
|
||||
"@tailwindcss/postcss": "^4.0.14",
|
||||
"@tanstack/eslint-plugin-query": "^5.83.1",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^20",
|
||||
"@types/node": "^20.19.0",
|
||||
"@types/pg": "^8.11.11",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"concurrently": "^9.1.2",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"drizzle-kit": "^0.30.4",
|
||||
"knip": "^5.61.2",
|
||||
"postcss": "^8",
|
||||
"react-email": "3.0.7",
|
||||
"tailwindcss": "^4.0.14",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5"
|
||||
"typescript": "^5.8.3",
|
||||
"wrangler": "^4.28.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
9248
pnpm-lock.yaml
generated
2
public/_headers
Normal file
@ -0,0 +1,2 @@
|
||||
/_next/static/*
|
||||
Cache-Control: public,max-age=31536000,immutable
|
Before Width: | Height: | Size: 476 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 313 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 308 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 299 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 308 KiB After Width: | Height: | Size: 63 KiB |