create-jant 0.2.4 → 0.2.5

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
@@ -8,7 +8,7 @@ import path from "path";
8
8
  import { fileURLToPath } from "url";
9
9
  var __filename = fileURLToPath(import.meta.url);
10
10
  var __dirname = path.dirname(__filename);
11
- var CORE_VERSION = "0.3.8";
11
+ var CORE_VERSION = "0.3.9";
12
12
  var TEMPLATE_DIR = fs.existsSync(path.resolve(__dirname, "../template")) ? path.resolve(__dirname, "../template") : path.resolve(__dirname, "../../../templates/jant-site");
13
13
  function isValidProjectName(name) {
14
14
  return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(name);
@@ -40,9 +40,11 @@ async function copyTemplate(config) {
40
40
  return true;
41
41
  }
42
42
  });
43
+ const secretsExampleFile = ".dev.vars.example";
44
+ const secretsFile = ".dev.vars";
43
45
  const renames = [
44
46
  ["_gitignore", ".gitignore"],
45
- ["_env.example", ".dev.vars.example"],
47
+ ["_env.example", secretsExampleFile],
46
48
  ["_github", ".github"]
47
49
  ];
48
50
  for (const [from, to] of renames) {
@@ -79,12 +81,32 @@ async function copyTemplate(config) {
79
81
  await fs.writeFile(wranglerPath, content, "utf-8");
80
82
  }
81
83
  const authSecret = generateAuthSecret();
82
- const devVarsContent = `# Generated by create-jant
84
+ let devVarsContent = `# Generated by create-jant
83
85
  # AUTH_SECRET is used for session encryption (better-auth)
84
86
  AUTH_SECRET=${authSecret}
85
87
  `;
88
+ if (config.s3) {
89
+ if (await fs.pathExists(wranglerPath)) {
90
+ let wContent = await fs.readFile(wranglerPath, "utf-8");
91
+ wContent = wContent.replace(
92
+ /^# STORAGE_DRIVER = "s3"/m,
93
+ 'STORAGE_DRIVER = "s3"'
94
+ );
95
+ wContent = wContent.replace(/^# S3_ENDPOINT = /m, "S3_ENDPOINT = ");
96
+ wContent = wContent.replace(/^# S3_BUCKET = /m, "S3_BUCKET = ");
97
+ wContent = wContent.replace(/^# S3_REGION = /m, "S3_REGION = ");
98
+ wContent = wContent.replace(/^# S3_PUBLIC_URL = /m, "S3_PUBLIC_URL = ");
99
+ wContent = wContent.replace(/\n\[\[r2_buckets\]\][^[]*/s, "\n");
100
+ await fs.writeFile(wranglerPath, wContent, "utf-8");
101
+ }
102
+ devVarsContent += `
103
+ # S3-compatible storage credentials
104
+ S3_ACCESS_KEY_ID=
105
+ S3_SECRET_ACCESS_KEY=
106
+ `;
107
+ }
86
108
  await fs.writeFile(
87
- path.join(targetDir, ".dev.vars"),
109
+ path.join(targetDir, secretsFile),
88
110
  devVarsContent,
89
111
  "utf-8"
90
112
  );
@@ -105,7 +127,7 @@ AUTH_SECRET=${authSecret}
105
127
  async function main() {
106
128
  console.log();
107
129
  p.intro(chalk.bgCyan.black(" create-jant "));
108
- program.name("create-jant").description("Create a new Jant project").argument("[project-name]", "Name of the project").option("-y, --yes", "Skip prompts and use defaults").parse();
130
+ program.name("create-jant").description("Create a new Jant project").argument("[project-name]", "Name of the project").option("-y, --yes", "Skip prompts and use defaults").option("--s3", "Use S3-compatible storage instead of Cloudflare R2").parse();
109
131
  const args = program.args;
110
132
  const opts = program.opts();
111
133
  let projectName;
@@ -163,7 +185,8 @@ async function main() {
163
185
  }
164
186
  const config = {
165
187
  projectName,
166
- targetDir
188
+ targetDir,
189
+ s3: opts.s3
167
190
  };
168
191
  const spinner2 = p.spinner();
169
192
  spinner2.start("Creating project...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jant",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Create a new Jant project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,5 +1,12 @@
1
- # Copy this file to .dev.vars and fill in the values
1
+ # Secrets do not commit this file
2
+ #
3
+ # Cloudflare Workers: copy to .dev.vars
4
+ # VPS / Docker: copy to .env
2
5
 
3
6
  # AUTH_SECRET must be at least 32 characters
4
7
  # Generate one with: openssl rand -base64 32
5
8
  AUTH_SECRET=your-secret-key-at-least-32-chars-long
9
+
10
+ # Required when STORAGE_DRIVER=s3:
11
+ # S3_ACCESS_KEY_ID=your-access-key
12
+ # S3_SECRET_ACCESS_KEY=your-secret-key
@@ -59,9 +59,7 @@ const header = `-- =============================================================
59
59
  `;
60
60
 
61
61
  const tables = [
62
- ["settings"],
63
- ["user"],
64
- ["account"],
62
+ // settings, user, account are preserved by reset-demo.sql — don't export
65
63
  ["posts", "SELECT * FROM posts WHERE deleted_at IS NULL"],
66
64
  ["collections"],
67
65
  ["post_collections"],
@@ -14,9 +14,8 @@ DELETE FROM posts;
14
14
  DELETE FROM collections;
15
15
  DELETE FROM redirects;
16
16
 
17
- -- Clear sessions (keep users for demo login capability)
18
- DELETE FROM session;
19
- DELETE FROM verification;
17
+ -- Sessions, users, accounts, and settings are preserved
18
+ -- (only content data is reset)
20
19
 
21
20
  -- Reset auto-increment counters
22
21
  DELETE FROM sqlite_sequence WHERE name IN ('posts', 'media', 'collections', 'redirects');
@@ -4,22 +4,6 @@
4
4
  -- Usage: mise run demo-reset
5
5
  -- =============================================================================
6
6
 
7
- -- settings
8
- INSERT INTO settings VALUES('ONBOARDING_STATUS','completed',1770657027);
9
- INSERT INTO settings VALUES('SITE_LANGUAGE','zh-Hans',1770673922);
10
- INSERT INTO settings VALUES('siteName','Jant Demo',1770689095);
11
- INSERT INTO settings VALUES('siteDescription','A demo site for Jant - Modern microblog for Cloudflare Workers',1770689095);
12
- INSERT INTO settings VALUES('siteUrl','https://demo.jant.me',1770689095);
13
- INSERT INTO settings VALUES('postsPerPage','10',1770689095);
14
- INSERT INTO settings VALUES('timezone','UTC',1770689095);
15
- INSERT INTO settings VALUES('language','en',1770689095);
16
-
17
- -- user
18
- INSERT INTO user VALUES('cV9uL2nAhiFTPKgJnoiKVKyesEoWBdkY','Demo User','demo@jant.me',0,NULL,'admin',1770657027,1770657027);
19
-
20
- -- account
21
- INSERT INTO account VALUES('ARFNGzzGCjXacVOYu9vVbq4dwL2XuecG','cV9uL2nAhiFTPKgJnoiKVKyesEoWBdkY','credential','cV9uL2nAhiFTPKgJnoiKVKyesEoWBdkY',NULL,NULL,NULL,NULL,NULL,NULL,'2f0586376d6b21415b93d39aa00b31c3:f7adf50ededaaf477b27eb095035dc38f20ed8baa349bd10762eb5a916602342f32ac21bc8e384047361d2c67d82dbd922c906cc8fa1c43da68d8fa76e414562',1770657027,1770657027);
22
-
23
7
  -- posts
24
8
  INSERT INTO posts VALUES(1,'article','featured','Welcome to Jant',NULL,'# Welcome to Jant Demo
25
9
 
@@ -62,9 +46,150 @@ pnpm dev
62
46
  INSERT INTO posts VALUES(2,'note','quiet',NULL,NULL,'This is a demo note. Notes are short posts without titles, perfect for quick thoughts and updates.','<p>This is a demo note. Notes are short posts without titles, perfect for quick thoughts and updates.</p>',NULL,NULL,NULL,NULL,NULL,NULL,1770685495,1770685495,1770685495);
63
47
  INSERT INTO posts VALUES(3,'link','quiet','Jant on GitHub',NULL,'Check out the source code and documentation for Jant.','<p>Check out the source code and documentation for Jant.</p>','https://github.com/nicepkg/jant','GitHub','github.com',NULL,NULL,NULL,1770681895,1770681895,1770681895);
64
48
  INSERT INTO posts VALUES(4,'quote','quiet',NULL,NULL,'The best way to predict the future is to invent it.','<p>The best way to predict the future is to invent it.</p>',NULL,'Alan Kay',NULL,NULL,NULL,NULL,1770678295,1770678295,1770678295);
49
+ INSERT INTO posts VALUES(5,'image','quiet',NULL,NULL,'Image 1','<p>Image 1</p>
50
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1770758516,1770758516,1770758516);
51
+ INSERT INTO posts VALUES(6,'image','quiet',NULL,NULL,'Image 2','<p>Image 2</p>
52
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1770758537,1770758537,1770759299);
53
+ INSERT INTO posts VALUES(7,'page','unlisted','About','about','> **Work in Progress**: This project is still under active development and not yet ready for use. See the latest build at [demo.jant.me](https://demo.jant.me).
54
+ >
55
+ > Demo login: `demo@jant.me` / `demodemo` — Dashboard: [demo.jant.me/dash](https://demo.jant.me/dash)
56
+
57
+ A personal microblogging system as smooth as <https://threads.com>.
58
+
59
+ > **Jant** = Jantelagen (Law of Jante)
60
+ > Low-key, de-socialized personal expression.
61
+
62
+ ## What is Jant?
63
+
64
+ Jant is a single-author microblog for people who want to share thoughts without the noise of social media. No followers, no likes, no retweets—just your words.
65
+
66
+ **Features**:
67
+
68
+ - Multiple content types: notes, articles, links, quotes, images
69
+ - Thread support for longer thoughts
70
+ - Collections for curated topics
71
+ - Beautiful, themeable design
72
+ - Deploys to Cloudflare Workers in minutes
73
+
74
+ ## Quick Start
75
+
76
+ ```bash
77
+ # Create a new Jant site
78
+ pnpm create jant my-blog
79
+
80
+ # Start development
81
+ cd my-blog
82
+ pnpm dev
83
+
84
+ # Deploy to Cloudflare
85
+ pnpm deploy
86
+ ```
87
+
88
+ ## Documentation
89
+
90
+ - [Getting Started](docs/getting-started.md)
91
+ - [Deployment](docs/deployment.md)
92
+ - [Configuration](docs/configuration.md)
93
+ - [Theming](docs/theming.md)
94
+ - [API Reference](docs/API.md)
95
+
96
+ ## Development
97
+
98
+ Requires [mise](https://mise.jdx.dev/) — it manages Node.js and pnpm automatically.
99
+
100
+ ```bash
101
+ # Install mise (macOS/Linux)
102
+ curl https://mise.run | sh
103
+
104
+ # Clone and setup
105
+ git clone https://github.com/jant-me/jant.git
106
+ cd jant
107
+ mise install # installs Node.js and pnpm
108
+ pnpm install # installs dependencies
109
+
110
+ # Start development server (http://localhost:9019)
111
+ mise run dev
112
+ ```
113
+
114
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for code style, PR process, and release workflow.
115
+
116
+ ## Philosophy
117
+
118
+ Jant is built on the idea that not everything needs to be optimized for engagement. Write for yourself. Share if you want. No metrics, no pressure.
119
+
120
+ ## License
121
+
122
+ AGPL-3.0
123
+ ','<blockquote>
124
+ <p><strong>Work in Progress</strong>: This project is still under active development and not yet ready for use. See the latest build at <a href="https://demo.jant.me">demo.jant.me</a>.</p>
125
+ <p>Demo login: <code>demo@jant.me</code> / <code>demodemo</code> — Dashboard: <a href="https://demo.jant.me/dash">demo.jant.me/dash</a></p>
126
+ </blockquote>
127
+ <p>A personal microblogging system as smooth as <a href="https://threads.com">https://threads.com</a>.</p>
128
+ <blockquote>
129
+ <p><strong>Jant</strong> = Jantelagen (Law of Jante)<br>Low-key, de-socialized personal expression.</p>
130
+ </blockquote>
131
+ <h2>What is Jant?</h2>
132
+ <p>Jant is a single-author microblog for people who want to share thoughts without the noise of social media. No followers, no likes, no retweets—just your words.</p>
133
+ <p><strong>Features</strong>:</p>
134
+ <ul>
135
+ <li>Multiple content types: notes, articles, links, quotes, images</li>
136
+ <li>Thread support for longer thoughts</li>
137
+ <li>Collections for curated topics</li>
138
+ <li>Beautiful, themeable design</li>
139
+ <li>Deploys to Cloudflare Workers in minutes</li>
140
+ </ul>
141
+ <h2>Quick Start</h2>
142
+ <pre><code class="language-bash"># Create a new Jant site
143
+ pnpm create jant my-blog
144
+
145
+ # Start development
146
+ cd my-blog
147
+ pnpm dev
148
+
149
+ # Deploy to Cloudflare
150
+ pnpm deploy
151
+ </code></pre>
152
+ <h2>Documentation</h2>
153
+ <ul>
154
+ <li><a href="docs/getting-started.md">Getting Started</a></li>
155
+ <li><a href="docs/deployment.md">Deployment</a></li>
156
+ <li><a href="docs/configuration.md">Configuration</a></li>
157
+ <li><a href="docs/theming.md">Theming</a></li>
158
+ <li><a href="docs/API.md">API Reference</a></li>
159
+ </ul>
160
+ <h2>Development</h2>
161
+ <p>Requires <a href="https://mise.jdx.dev/">mise</a> — it manages Node.js and pnpm automatically.</p>
162
+ <pre><code class="language-bash"># Install mise (macOS/Linux)
163
+ curl https://mise.run | sh
164
+
165
+ # Clone and setup
166
+ git clone https://github.com/jant-me/jant.git
167
+ cd jant
168
+ mise install # installs Node.js and pnpm
169
+ pnpm install # installs dependencies
170
+
171
+ # Start development server (http://localhost:9019)
172
+ mise run dev
173
+ </code></pre>
174
+ <p>See <a href="CONTRIBUTING.md">CONTRIBUTING.md</a> for code style, PR process, and release workflow.</p>
175
+ <h2>Philosophy</h2>
176
+ <p>Jant is built on the idea that not everything needs to be optimized for engagement. Write for yourself. Share if you want. No metrics, no pressure.</p>
177
+ <h2>License</h2>
178
+ <p>AGPL-3.0</p>
179
+ ',NULL,NULL,NULL,NULL,NULL,NULL,1770759271,1770759271,1770759271);
65
180
 
66
181
  -- collections
67
182
  INSERT INTO collections VALUES(1,'getting-started','Getting Started','Resources for getting started with Jant',1770689095,1770689095);
183
+ INSERT INTO collections VALUES(2,'inspires','Inspires',NULL,1770758555,1770758555);
68
184
 
69
185
  -- post_collections
70
186
  INSERT INTO post_collections VALUES(1,1,1770689095);
187
+ INSERT INTO post_collections VALUES(6,2,1770758568);
188
+
189
+ -- media
190
+ INSERT INTO media VALUES('019c496c-46bd-7954-bd6a-77b1b8f1d451',NULL,'019c496c-46bd-7954-bd6a-77b1b8f1d451.webp','tegan-conway-KaFfNTw8OYQ-unsplash.webp','image/webp',715364,'media/2026/02/019c496c-46bd-7954-bd6a-77b1b8f1d451.webp',NULL,NULL,NULL,1770758358,0,NULL);
191
+ INSERT INTO media VALUES('019c496c-5e44-70d2-ac8a-c0c0bdaab65c',6,'019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp','land-o-lakes-inc-9w6Qb-dqBwE-unsplash.webp','image/webp',306042,'media/2026/02/019c496c-5e44-70d2-ac8a-c0c0bdaab65c.webp',NULL,NULL,NULL,1770758364,3,NULL);
192
+ INSERT INTO media VALUES('019c496d-5011-7981-89a0-b4373a695d78',6,'019c496d-5011-7981-89a0-b4373a695d78.webp','land-o-lakes-inc-k71TQkbVIgI-unsplash.webp','image/webp',597680,'media/2026/02/019c496d-5011-7981-89a0-b4373a695d78.webp',NULL,NULL,NULL,1770758426,2,NULL);
193
+ INSERT INTO media VALUES('019c496d-630c-70b4-9004-51a194746566',6,'019c496d-630c-70b4-9004-51a194746566.webp','thingsneverchange-CgHNmQ0c2w4-unsplash.webp','image/webp',358320,'media/2026/02/019c496d-630c-70b4-9004-51a194746566.webp',NULL,NULL,NULL,1770758431,1,NULL);
194
+ INSERT INTO media VALUES('019c496d-720f-70d2-98b8-3779457de73c',6,'019c496d-720f-70d2-98b8-3779457de73c.webp','willian-justen-de-vasconcellos-7jg7Y_Mlf2Q-unsplash.webp','image/webp',478956,'media/2026/02/019c496d-720f-70d2-98b8-3779457de73c.webp',NULL,NULL,NULL,1770758435,0,NULL);
195
+ INSERT INTO media VALUES('019c496e-6904-7f61-b14f-080035ffe23f',5,'019c496e-6904-7f61-b14f-080035ffe23f.webp','richard-stachmann-Es--yoQocSM-unsplash.webp','image/webp',381534,'media/2026/02/019c496e-6904-7f61-b14f-080035ffe23f.webp',NULL,NULL,NULL,1770758498,0,NULL);
@@ -39,6 +39,15 @@ R2_PUBLIC_URL = "https://demo-media.jant.me" # @create-jant: @remove
39
39
  # DEMO_EMAIL = "demo@example.com"
40
40
  # DEMO_PASSWORD = "demo123"
41
41
 
42
+ # Optional: S3-compatible storage (alternative to R2)
43
+ # Set STORAGE_DRIVER = "s3" and configure the options below.
44
+ # When using S3, the [[r2_buckets]] section can be removed.
45
+ STORAGE_DRIVER = "s3"
46
+ S3_ENDPOINT = "https://s3.us-east-005.backblazeb2.com"
47
+ S3_BUCKET = "jant-media"
48
+ S3_REGION = "us-east-005"
49
+ S3_PUBLIC_URL = "https://files.owenyoung.com/file/jant-media"
50
+
42
51
  [[d1_databases]]
43
52
  binding = "DB"
44
53
  database_name = "jant-site-db" # @create-jant: "${name}-db"