create-jant 0.3.24 → 0.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import path from "path";
9
9
  import { fileURLToPath } from "url";
10
10
  var __filename = fileURLToPath(import.meta.url);
11
11
  var __dirname = path.dirname(__filename);
12
- var CORE_VERSION = "0.3.24";
12
+ var CORE_VERSION = "0.3.26";
13
13
  var TEMPLATE_DIR = fs.existsSync(path.resolve(__dirname, "../template")) ? path.resolve(__dirname, "../template") : path.resolve(__dirname, "../../../templates/jant-site");
14
14
  function isValidProjectName(name) {
15
15
  return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jant",
3
- "version": "0.3.24",
3
+ "version": "0.3.26",
4
4
  "description": "Create a new Jant project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -207,65 +207,60 @@ For all available variables (site name, language, R2 storage, image optimization
207
207
 
208
208
  ## Customization
209
209
 
210
- ### Theme Components
210
+ ### Color Themes
211
211
 
212
- Override theme components by creating files in `src/theme/components/`:
212
+ Pick a color theme from the dashboard: **Settings > Appearance**.
213
213
 
214
- ```typescript
215
- // src/theme/components/PostCard.tsx
216
- import type { PostCardProps } from "@jant/core";
217
- import { PostCard as OriginalPostCard } from "@jant/core/theme";
218
-
219
- export function PostCard(props: PostCardProps) {
220
- return (
221
- <div class="my-wrapper">
222
- <OriginalPostCard {...props} />
223
- </div>
224
- );
225
- }
226
- ```
214
+ ### Custom CSS
227
215
 
228
- Then register it in `src/index.ts`:
216
+ Inject custom CSS from the dashboard: **Settings > Appearance > Custom CSS**. This CSS is applied with the highest priority, so you can override any built-in styles.
229
217
 
230
- ```typescript
231
- import { createApp } from "@jant/core";
232
- import { PostCard } from "./theme/components/PostCard";
218
+ ### CSS Design Tokens
233
219
 
234
- export default createApp({
235
- theme: {
236
- components: {
237
- PostCard,
238
- },
239
- },
240
- });
220
+ Override design tokens in your custom CSS to change the look and feel:
221
+
222
+ ```css
223
+ :root {
224
+ --site-width: 720px;
225
+ --card-radius: 0.5rem;
226
+ --font-body: "Inter", system-ui, sans-serif;
227
+ --avatar-size: 42px;
228
+ }
241
229
  ```
242
230
 
243
- ### Custom Styles
231
+ ### Data Attributes
244
232
 
245
- Add custom CSS in `src/theme/styles/`:
233
+ Target specific elements with stable data attributes:
246
234
 
247
235
  ```css
248
- /* src/theme/styles/custom.css */
249
- @import "@jant/core/theme/styles/main.css";
236
+ /* Style only note-format posts */
237
+ [data-format="note"] {
238
+ border-left: 3px solid var(--primary);
239
+ }
240
+
241
+ /* Style the home page differently */
242
+ [data-page="home"] {
243
+ background: var(--muted);
244
+ }
250
245
 
251
- /* Your custom styles */
252
- .my-custom-class {
253
- /* ... */
246
+ /* Hide compose prompt for unauthenticated visitors */
247
+ body:not([data-authenticated]) .compose-prompt {
248
+ display: none;
254
249
  }
255
250
  ```
256
251
 
257
- ### Using Third-Party Themes
252
+ ### Code-Level Customization
258
253
 
259
- ```bash
260
- npm install @jant-themes/minimal
261
- ```
254
+ Pass CSS variable overrides or custom color themes via `createApp()`:
262
255
 
263
256
  ```typescript
264
257
  import { createApp } from "@jant/core";
265
- import { theme as MinimalTheme } from "@jant-themes/minimal";
266
258
 
267
259
  export default createApp({
268
- theme: MinimalTheme,
260
+ cssVariables: {
261
+ "--site-width": "720px",
262
+ "--card-radius": "0.5rem",
263
+ },
269
264
  });
270
265
  ```
271
266
 
@@ -55,12 +55,12 @@ const header = `-- =============================================================
55
55
 
56
56
  const tables = [
57
57
  ...(!noAuth ? [["settings"], ["user"], ["account"]] : []),
58
+ ["pages"],
59
+ ["collections"],
58
60
  [
59
61
  "posts",
60
62
  "SELECT * FROM posts WHERE deleted_at IS NULL",
61
63
  ],
62
- ["pages"],
63
- ["collections"],
64
64
  ["nav_items"],
65
65
  ];
66
66
 
@@ -7,24 +7,29 @@
7
7
  -- Reset (clear existing content)
8
8
  DELETE FROM posts_fts;
9
9
 
10
- DELETE FROM post_collections;
11
-
10
+ DELETE FROM nav_items;
12
11
  DELETE FROM media;
13
12
  DELETE FROM posts;
13
+ DELETE FROM pages;
14
14
  DELETE FROM collections;
15
15
  DELETE FROM redirects;
16
16
 
17
17
 
18
- DELETE FROM sqlite_sequence WHERE name IN ('posts', 'media', 'collections', 'redirects');
18
+ DELETE FROM sqlite_sequence WHERE name IN ('posts', 'pages', 'collections', 'nav_items', 'redirects');
19
19
 
20
20
  -- posts
21
- INSERT INTO posts VALUES(4,'note','quiet',NULL,NULL,'没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。','<p>没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。</p>
21
+ INSERT INTO posts VALUES(1,'note','published',0,0,NULL,'really?',NULL,'is this works?','<p>is this works?</p>
22
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1771089786,1771089786,1771089786);
23
+ INSERT INTO posts VALUES(2,'quote','published',0,0,NULL,NULL,NULL,NULL,NULL,'worked?',NULL,NULL,NULL,NULL,NULL,1771089808,1771089808,1771089808);
24
+ INSERT INTO posts VALUES(3,'note','published',0,0,NULL,'greate image',NULL,'great','<p>great</p>
25
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1771092931,1771092931,1771268464);
26
+ INSERT INTO posts VALUES(4,'note','published',0,0,NULL,NULL,NULL,'没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。','<p>没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。</p>
22
27
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771114861,1771114861,1771114861);
23
- INSERT INTO posts VALUES(5,'note','quiet',NULL,NULL,'新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。"。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。','<p>新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。&quot;。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。</p>
28
+ INSERT INTO posts VALUES(5,'note','published',0,0,NULL,NULL,NULL,'新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。"。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。','<p>新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。&quot;。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。</p>
24
29
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771114906,1771114906,1771114906);
25
- INSERT INTO posts VALUES(6,'link','quiet','Forty News',NULL,'40年前今日的新闻...','<p>40年前今日的新闻...</p>
26
- ','https://forty.news/',NULL,'forty.news',NULL,NULL,NULL,1771114955,1771114955,1771114955);
27
- INSERT INTO posts VALUES(7,'article','quiet','我从 Hacker News 中学到了什么?',NULL,'昨天看到 Hacker News 的创始人 Paul Graham 在 2009
30
+ INSERT INTO posts VALUES(6,'link','published',0,0,NULL,'Forty News','https://forty.news/','40年前今日的新闻...','<p>40年前今日的新闻...</p>
31
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1771114955,1771114955,1771114955);
32
+ INSERT INTO posts VALUES(7,'note','published',0,0,NULL,'我从 Hacker News 中学到了什么?',NULL,'昨天看到 Hacker News 的创始人 Paul Graham 在 2009
28
33
  年写的一篇文章[《我从 Hacker News 中学到了什么》](http://www.paulgraham.com/hackernews.html),
29
34
  作者提到:
30
35
 
@@ -89,7 +94,7 @@ RSS。没有使用任何框架,就几句简单的 deno
89
94
  2 篇文章,而现在[HN 首页](https://hackernews.buzzing.cc/)可以放 20 多篇,效率直接提升 10 倍啊有木有。
90
95
 
91
96
  很快,我发现按照这样布局的话,阅读效率高了太多了,已有的这些时间流,已经不够我看了,所以索性单独为我自己生成一个[HN 时间流](https://myfeed.owenyoung.com/),里面包含了
92
- hn 上前 100 位用户提交的任何帖子。
97
+ hn 上前 100 位用户提交的任何帖子。
93
98
 
94
99
  几天之后我就发现,之前只看 HN 的热门帖子损失有多大,HN
95
100
  上有太多优秀的内容没有被顶上去了。热门真的很随机,所以我们也要万分警惕大公司的算法机制。基于此,我又做了一个变化,直接抓取 HN 上最新的提交(我去掉了 Ask
@@ -109,7 +114,7 @@ HN 上所有最新的文章了。即使是全部文章,由于是母语阅读
109
114
 
110
115
  比如我读了上面推荐的[《深度工作》](https://d.buzzing.cc/post/1),作者提到:
111
116
 
112
- > “如果在你全部的清醒时间,都能给自己的大脑找到有意义的事情去做,而不是放任自己在迷糊的状态下漫无目的地浏览几个小时网页,那么在一天结束时,你会觉得更加充实,第二天开始时更加轻松。
117
+ > "如果在你全部的清醒时间,都能给自己的大脑找到有意义的事情去做,而不是放任自己在迷糊的状态下漫无目的地浏览几个小时网页,那么在一天结束时,你会觉得更加充实,第二天开始时更加轻松。
113
118
  > – 卡尔·纽波特《深度工作》
114
119
 
115
120
  从我沉迷 HN
@@ -156,27 +161,27 @@ HN 上所有最新的文章了。即使是全部文章,由于是母语阅读
156
161
  </ul>
157
162
  <p>比如我读了上面推荐的<a href="https://d.buzzing.cc/post/1">《深度工作》</a>,作者提到:</p>
158
163
  <blockquote>
159
- <p>“如果在你全部的清醒时间,都能给自己的大脑找到有意义的事情去做,而不是放任自己在迷糊的状态下漫无目的地浏览几个小时网页,那么在一天结束时,你会觉得更加充实,第二天开始时更加轻松。<br>– 卡尔·纽波特《深度工作》</p>
164
+ <p>"如果在你全部的清醒时间,都能给自己的大脑找到有意义的事情去做,而不是放任自己在迷糊的状态下漫无目的地浏览几个小时网页,那么在一天结束时,你会觉得更加充实,第二天开始时更加轻松。<br>– 卡尔·纽波特《深度工作》</p>
160
165
  </blockquote>
161
166
  <p>从我沉迷 HN<br>的例子里就能看出,网络已经剥夺了我保持专注和沉思的能力,但是真正值得探索和学习的知识都需要我拥有这种能力。如果我没有在某一个特定时段给自己安排任务,那么这些网站总是会更有诱惑力。所以如果我想抵御社交网络对我时间和精力的诱惑,那么必须要给大脑找一些高质量的替代活动,所以我基于开源<br><a href="https://lemmy.ml/">Lemmy</a> 搭建了一个类似 Reddit<br>的社区,叫<a href="https://d.buzzing.cc/"><strong>如何度过每一天</strong></a>,希望能在社区里分享有意义的事,不虚度光阴的事,可以是阅读某本书,学习某项技能,看某部纪录片等等等等。社区有投票的功能,某项活动被投票的次数越多,说明认为这项活动有意义的更多。</p>
162
167
  <p>目前其实就只有少数几个用户在用,网站依然是部署在我的一个 廉价 VPS 上,没有盈利的打算,目前加载也有点慢,但是够用。</p>
163
168
  <p>以上是我在 Hacker News 上学到的一些东西。</p>
164
169
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771115051,1771115051,1771115051);
165
- INSERT INTO posts VALUES(8,'quote','quiet',NULL,NULL,'拥有五万个从不打开邮件的订阅者名单,其价值远不及五百个逐字阅读并偶尔给予深度回复的读者。后者会购买你的著作,向朋友推荐你,并长久陪伴你。前者不过是你在那些无聊的数字炫耀派对上能拿出来吹嘘的数字而已。','<p>拥有五万个从不打开邮件的订阅者名单,其价值远不及五百个逐字阅读并偶尔给予深度回复的读者。后者会购买你的著作,向朋友推荐你,并长久陪伴你。前者不过是你在那些无聊的数字炫耀派对上能拿出来吹嘘的数字而已。</p>
166
- ','https://www.joanwestenberg.com/why-my-newsletter-costs-2-50/',NULL,'www.joanwestenberg.com',NULL,NULL,NULL,1771115103,1771115103,1771115103);
167
- INSERT INTO posts VALUES(9,'quote','featured',NULL,NULL,'弗吉尼亚·伍尔夫曾论述拥有独立空间的重要性:那是供人进行创作的物理场所,不受干扰与控制。博客便是网络世界中的独立空间。在这里,你自主决定书写内容与表达方式,无需屈从于平台算法的任性摆布——那些平台只顾榨取你的参与度,却不关心这种参与究竟是否让你或他人变得更聪明。
168
-
169
- 我们不会通过等待平台减少剥削来获得更好的互联网。我们需要亲手构建它——维护自己的空间,相互链接,打造独立网站的互联网络,让博客圈重现昔日的辉煌。','<p>弗吉尼亚·伍尔夫曾论述拥有独立空间的重要性:那是供人进行创作的物理场所,不受干扰与控制。博客便是网络世界中的独立空间。在这里,你自主决定书写内容与表达方式,无需屈从于平台算法的任性摆布——那些平台只顾榨取你的参与度,却不关心这种参与究竟是否让你或他人变得更聪明。</p>
170
- <p>我们不会通过等待平台减少剥削来获得更好的互联网。我们需要亲手构建它——维护自己的空间,相互链接,打造独立网站的互联网络,让博客圈重现昔日的辉煌。</p>
171
- ','https://www.joanwestenberg.com/the-case-for-blogging-in-the-ruins/','JA Westenberg','www.joanwestenberg.com',NULL,NULL,NULL,1771115159,1771115159,1771115177);
172
- INSERT INTO posts VALUES(10,'link','quiet','Some pics',NULL,'一个干净的图片流网站
170
+ INSERT INTO posts VALUES(8,'quote','published',0,0,NULL,NULL,'https://www.joanwestenberg.com/why-my-newsletter-costs-2-50/',NULL,NULL,'拥有五万个从不打开邮件的订阅者名单,其价值远不及五百个逐字阅读并偶尔给予深度回复的读者。后者会购买你的著作,向朋友推荐你,并长久陪伴你。前者不过是你在那些无聊的数字炫耀派对上能拿出来吹嘘的数字而已。',NULL,NULL,NULL,NULL,NULL,1771115103,1771115103,1771115103);
171
+ INSERT INTO posts VALUES(9,'quote','published',1,0,NULL,'JA Westenberg','https://www.joanwestenberg.com/the-case-for-blogging-in-the-ruins/',NULL,NULL,'弗吉尼亚·伍尔夫曾论述拥有独立空间的重要性:那是供人进行创作的物理场所,不受干扰与控制。博客便是网络世界中的独立空间。在这里,你自主决定书写内容与表达方式,无需屈从于平台算法的任性摆布——那些平台只顾榨取你的参与度,却不关心这种参与究竟是否让你或他人变得更聪明。
172
+
173
+ 我们不会通过等待平台减少剥削来获得更好的互联网。我们需要亲手构建它——维护自己的空间,相互链接,打造独立网站的互联网络,让博客圈重现昔日的辉煌。',NULL,NULL,NULL,NULL,NULL,1771115159,1771115159,1771115177);
174
+ INSERT INTO posts VALUES(10,'link','published',0,0,NULL,'Some pics','https://some.pics/','一个干净的图片流网站
173
175
  ','<p>一个干净的图片流网站</p>
174
- ','https://some.pics/',NULL,'some.pics',NULL,NULL,NULL,1771115271,1771115271,1771115271);
175
- INSERT INTO posts VALUES(11,'image','quiet',NULL,NULL,'From upsplash','<p>From upsplash</p>
176
- ',NULL,NULL,NULL,NULL,NULL,NULL,1771123457,1771123457,1771123457);
176
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1771115271,1771115271,1771115271);
177
+ INSERT INTO posts VALUES(11,'note','published',0,0,NULL,NULL,NULL,'From splash','<p>From splash</p>
178
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1771268320,1771268320,1771268958);
177
179
 
178
180
  -- media
179
- INSERT INTO media VALUES('019c5f2e-6d5f-74f3-a521-d4fbac0b4ac3',NULL,'019c5f2e-6d5f-74f3-a521-d4fbac0b4ac3.webp','brianna-parks-frXRtKYPqXk-unsplash.webp','image/webp',264554,'media/2026/02/019c5f2e-6d5f-74f3-a521-d4fbac0b4ac3.webp',NULL,NULL,NULL,1771123404,0,NULL,'r2');
180
- INSERT INTO media VALUES('019c5f2e-7dea-729c-a260-6c006faf3384',11,'019c5f2e-7dea-729c-a260-6c006faf3384.webp','land-o-lakes-inc-peEOQ4_dqOo-unsplash.webp','image/webp',470774,'media/2026/02/019c5f2e-7dea-729c-a260-6c006faf3384.webp',NULL,NULL,NULL,1771123408,1,NULL,'r2');
181
- INSERT INTO media VALUES('019c5f2e-8a17-77dc-a91c-2d51f14a622c',NULL,'019c5f2e-8a17-77dc-a91c-2d51f14a622c.webp','museum-of-new-zealand-te-papa-tongarewa-1C7oRRwUkgU-unsplash.webp','image/webp',322656,'media/2026/02/019c5f2e-8a17-77dc-a91c-2d51f14a622c.webp',NULL,NULL,NULL,1771123411,0,NULL,'r2');
182
- INSERT INTO media VALUES('019c5f2e-96d2-7e56-801a-6073bd6183f6',11,'019c5f2e-96d2-7e56-801a-6073bd6183f6.webp','takashi-sakamoto-J9nW9Tc1HVc-unsplash.webp','image/webp',505172,'media/2026/02/019c5f2e-96d2-7e56-801a-6073bd6183f6.webp',NULL,NULL,NULL,1771123415,0,NULL,'r2');
181
+ INSERT INTO media VALUES('019c676d-1fcd-7c11-9737-5aebd10c1087',3,'019c676d-1fcd-7c11-9737-5aebd10c1087.webp','ansis-kancs-XGxp1rvTVag-unsplash.webp','image/webp',202748,'media/2026/02/019c676d-1fcd-7c11-9737-5aebd10c1087.webp',NULL,NULL,NULL,1771261731,0,NULL,'r2');
182
+ INSERT INTO media VALUES('019c679e-98f9-73ba-bd57-ab6ebf94fe05',3,'019c679e-98f9-73ba-bd57-ab6ebf94fe05.webp','dan-begel-pbfkmEL3QaU-unsplash.webp','image/webp',229392,'media/2026/02/019c679e-98f9-73ba-bd57-ab6ebf94fe05.webp',NULL,NULL,NULL,1771264973,1,NULL,'r2');
183
+ INSERT INTO media VALUES('019c679e-a8ce-7d49-9c21-8d75a1551198',3,'019c679e-a8ce-7d49-9c21-8d75a1551198.webp','willian-justen-de-vasconcellos--pKhrem8YpE-unsplash.webp','image/webp',324826,'media/2026/02/019c679e-a8ce-7d49-9c21-8d75a1551198.webp',NULL,NULL,NULL,1771264977,2,NULL,'r2');
184
+ INSERT INTO media VALUES('019c679e-c351-76dc-9569-2a716b4384b5',NULL,'019c679e-c351-76dc-9569-2a716b4384b5.webp','brianna-parks-frXRtKYPqXk-unsplash.webp','image/webp',264554,'media/2026/02/019c679e-c351-76dc-9569-2a716b4384b5.webp',NULL,NULL,NULL,1771264984,0,NULL,'r2');
185
+ INSERT INTO media VALUES('019c67d5-1022-7efd-9ae8-0454325cba78',NULL,'019c67d5-1022-7efd-9ae8-0454325cba78.webp','takashi-sakamoto-J9nW9Tc1HVc-unsplash.webp','image/webp',505172,'media/2026/02/019c67d5-1022-7efd-9ae8-0454325cba78.webp',NULL,NULL,NULL,1771268543,0,NULL,'r2');
186
+ INSERT INTO media VALUES('019c67d5-28b8-7ec3-ae2e-83d9eb1b096b',NULL,'019c67d5-28b8-7ec3-ae2e-83d9eb1b096b.webp','museum-of-new-zealand-te-papa-tongarewa-1C7oRRwUkgU-unsplash.webp','image/webp',322656,'media/2026/02/019c67d5-28b8-7ec3-ae2e-83d9eb1b096b.webp',NULL,NULL,NULL,1771268549,0,NULL,'r2');
187
+ INSERT INTO media VALUES('019c67d5-39c9-7723-8b0c-4c8a50076dc3',11,'019c67d5-39c9-7723-8b0c-4c8a50076dc3.webp','land-o-lakes-inc-peEOQ4_dqOo-unsplash.webp','image/webp',470774,'media/2026/02/019c67d5-39c9-7723-8b0c-4c8a50076dc3.webp',NULL,NULL,NULL,1771268554,0,NULL,'r2');
@@ -13,6 +13,14 @@ INSERT INTO user VALUES('xCkM3BgGOkgQnec6l8EF3f4q2VnG6AoU','test','theowenyoung@
13
13
  -- account
14
14
  INSERT INTO account VALUES('jC56rT53Pe9aXkrv4YtlCBuPQACWoOuY','xCkM3BgGOkgQnec6l8EF3f4q2VnG6AoU','credential','xCkM3BgGOkgQnec6l8EF3f4q2VnG6AoU',NULL,NULL,NULL,NULL,NULL,NULL,'3d915508e712a5b481109e907ae99cc2:5303d92b81403b2a77a1a65d58586c781d896e8ba71c02ea19207f94e2e9d9ebf82a2e9fd1f1a61556aee6cd7dcdf07c70cb64f6fe42d30e05870b2f7b90c27c',1770761877,1770761877);
15
15
 
16
+ -- pages
17
+ INSERT INTO pages VALUES(1,'about','About','
18
+ Yes about','<p>Yes about</p>
19
+ ','published',1771272645,1771273719);
20
+
21
+ -- collections
22
+ INSERT INTO collections VALUES(1,'best-quotes','发人深省',NULL,NULL,'newest',0,0,1771273707,1771273707);
23
+
16
24
  -- posts
17
25
  INSERT INTO posts VALUES(1,'note','published',0,0,NULL,'really?',NULL,'is this works?','<p>is this works?</p>
18
26
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771089786,1771089786,1771089786);
@@ -22,7 +30,7 @@ INSERT INTO posts VALUES(3,'note','published',0,0,NULL,'greate image',NULL,'grea
22
30
  INSERT INTO posts VALUES(4,'note','published',0,0,NULL,NULL,NULL,'没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。','<p>没有人真的想交付自己都看不上的东西。我们天然就想把事情做得更对一点、更好一点。</p>
23
31
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771114861,1771114861,1771114861);
24
32
  INSERT INTO posts VALUES(5,'note','published',0,0,NULL,NULL,NULL,'新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。"。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。','<p>新荣记的老板会给出预算,让店长和主厨每两周可以自己订一家餐厅去体验,而且预算没有上限。从到东京筹备开店至今,他们已经吃了日本十几家不同的餐厅。很多餐厅的服务员从没吃过自家餐厅的招牌菜,而新荣记不但安排自己的厨师和服务人员吃自己家的菜,还会提供费用,让这些年轻人去他们向往的餐厅,体验别人家的优点。&quot;。我想,对我们网上冲浪的启发就是我们也要多体验别人做的好东西,从中提高审美和获得灵感。</p>
25
- ',NULL,NULL,NULL,NULL,NULL,NULL,1771114906,1771114906,1771114906);
33
+ ',NULL,NULL,1,NULL,NULL,NULL,1771114906,1771114906,1771273733);
26
34
  INSERT INTO posts VALUES(6,'link','published',0,0,NULL,'Forty News','https://forty.news/','40年前今日的新闻...','<p>40年前今日的新闻...</p>
27
35
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771114955,1771114955,1771114955);
28
36
  INSERT INTO posts VALUES(7,'note','published',0,0,NULL,'我从 Hacker News 中学到了什么?',NULL,'昨天看到 Hacker News 的创始人 Paul Graham 在 2009
@@ -173,6 +181,12 @@ INSERT INTO posts VALUES(10,'link','published',0,0,NULL,'Some pics','https://som
173
181
  INSERT INTO posts VALUES(11,'note','published',0,0,NULL,NULL,NULL,'From splash','<p>From splash</p>
174
182
  ',NULL,NULL,NULL,NULL,NULL,NULL,1771268320,1771268320,1771268958);
175
183
 
184
+ -- nav_items
185
+ INSERT INTO nav_items VALUES(1,'link','Featured','/featured',NULL,1,1771272664,1771273781);
186
+ INSERT INTO nav_items VALUES(2,'link','Collections','/collections',NULL,2,1771272682,1771273781);
187
+ INSERT INTO nav_items VALUES(4,'page','About','/about',1,3,1771272722,1771273781);
188
+ INSERT INTO nav_items VALUES(5,'link','Home','/',NULL,0,1771273779,1771273781);
189
+
176
190
  -- media
177
191
  INSERT INTO media VALUES('019c676d-1fcd-7c11-9737-5aebd10c1087',3,'019c676d-1fcd-7c11-9737-5aebd10c1087.webp','ansis-kancs-XGxp1rvTVag-unsplash.webp','image/webp',202748,'media/2026/02/019c676d-1fcd-7c11-9737-5aebd10c1087.webp',NULL,NULL,NULL,1771261731,0,NULL,'r2');
178
192
  INSERT INTO media VALUES('019c679e-98f9-73ba-bd57-ab6ebf94fe05',3,'019c679e-98f9-73ba-bd57-ab6ebf94fe05.webp','dan-begel-pbfkmEL3QaU-unsplash.webp','image/webp',229392,'media/2026/02/019c679e-98f9-73ba-bd57-ab6ebf94fe05.webp',NULL,NULL,NULL,1771264973,1,NULL,'r2');
@@ -2,7 +2,7 @@
2
2
  * Jant Site Entry Point
3
3
  *
4
4
  * This is the main entry point for your Jant site.
5
- * The threads theme is used by default. To customize, pass options to createApp().
5
+ * Customize with CSS variables, color themes, or custom CSS in the dashboard.
6
6
  *
7
7
  * Configuration:
8
8
  * - Site settings (name, description, language) should be configured via
@@ -30,13 +30,17 @@ SITE_URL = ""
30
30
  # Optional: Timeline page size (default: 20)
31
31
  # PAGE_SIZE = "5"
32
32
 
33
- # Optional: R2 Storage (for media uploads)
33
+ # Recommended: R2 public URL for media access
34
+ # Without this, media files are proxied through your Worker (slower, uses more CPU).
35
+ # With this, media is served directly from Cloudflare's CDN (faster, lower cost).
36
+ # Set up: Cloudflare Dashboard → R2 → Your Bucket → Settings → Public access
34
37
  # R2_PUBLIC_URL = "https://cdn.example.com"
35
38
  R2_PUBLIC_URL = "https://demo-media.jant.me" # @create-jant: @remove
36
39
 
37
40
  # Optional: Cloudflare Image Transformations
38
41
  # For automatic thumbnail generation and image optimization
39
- # IMAGE_TRANSFORM_URL = "https://example.com/cdn-cgi/image"
42
+ # Use the same domain as R2_PUBLIC_URL (or SITE_URL if R2_PUBLIC_URL is not set)
43
+ # IMAGE_TRANSFORM_URL = "https://media.yourdomain.com/cdn-cgi/image"
40
44
 
41
45
  # Optional: Demo mode (pre-fill sign-in credentials)
42
46
  # DEMO_EMAIL = "demo@example.com"
@@ -1,21 +0,0 @@
1
- #!/bin/sh
2
- basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
-
4
- case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
10
- esac
11
-
12
- if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/home/runner/work/jant/jant/packages/core/bin/node_modules:/home/runner/work/jant/jant/packages/core/node_modules:/home/runner/work/jant/jant/packages/node_modules:/home/runner/work/jant/jant/node_modules:/home/runner/work/jant/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
14
- else
15
- export NODE_PATH="/home/runner/work/jant/jant/packages/core/bin/node_modules:/home/runner/work/jant/jant/packages/core/node_modules:/home/runner/work/jant/jant/packages/node_modules:/home/runner/work/jant/jant/node_modules:/home/runner/work/jant/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
16
- fi
17
- if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../@jant/core/bin/jant.js" "$@"
19
- else
20
- exec node "$basedir/../@jant/core/bin/jant.js" "$@"
21
- fi