create-jant 0.1.20 → 0.1.22

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.2.17";
11
+ var CORE_VERSION = "0.2.18";
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jant",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "Create a new Jant project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -55,6 +55,7 @@
55
55
  "typecheck": "tsc --noEmit",
56
56
  "copy-template": "rm -rf template && cp -r ../../templates/jant-site template",
57
57
  "prepare-template": "node scripts/prepare-template.js",
58
- "inject-version": "node -e \"const fs=require('fs');const v=require('../core/package.json').version;const f='dist/index.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace('__JANT_CORE_VERSION__',v))\""
58
+ "inject-version": "node -e \"const fs=require('fs');const v=require('../core/package.json').version;const f='dist/index.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace('__JANT_CORE_VERSION__',v))\"",
59
+ "test-template": "node scripts/test-template.js"
59
60
  }
60
61
  }
@@ -1,10 +1 @@
1
- {
2
- "semi": true,
3
- "singleQuote": false,
4
- "tabWidth": 2,
5
- "useTabs": false,
6
- "trailingComma": "es5",
7
- "printWidth": 100,
8
- "arrowParens": "always",
9
- "endOfLine": "lf"
10
- }
1
+ {}
@@ -170,10 +170,16 @@ To use your own domain:
170
170
 
171
171
  ## Environment Variables
172
172
 
173
- | Variable | Description | Required |
174
- | ------------- | ----------------------------------------- | -------------------- |
175
- | `AUTH_SECRET` | Secret key for authentication (32+ chars) | Yes |
176
- | `SITE_URL` | Your site's public URL | Set in wrangler.toml |
173
+ Core environment variables:
174
+
175
+ | Variable | Description | Location |
176
+ | ------------- | ----------------------------------------- | ---------------- |
177
+ | `AUTH_SECRET` | Secret key for authentication (32+ chars) | `.dev.vars` file |
178
+ | `SITE_URL` | Your site's public URL | `wrangler.toml` |
179
+
180
+ For a complete list of all available environment variables (site configuration, R2 storage, image optimization, demo mode, etc.), see:
181
+
182
+ **[📖 Full Configuration Guide](../../docs/configuration.md)**
177
183
 
178
184
  ## Customization
179
185
 
@@ -17,16 +17,16 @@ CREATE TABLE `account` (
17
17
  --> statement-breakpoint
18
18
  CREATE TABLE `collections` (
19
19
  `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
20
- `slug` text NOT NULL,
20
+ `path` text,
21
21
  `title` text NOT NULL,
22
22
  `description` text,
23
23
  `created_at` integer NOT NULL,
24
24
  `updated_at` integer NOT NULL
25
25
  );
26
26
  --> statement-breakpoint
27
- CREATE UNIQUE INDEX `collections_slug_unique` ON `collections` (`slug`);--> statement-breakpoint
27
+ CREATE UNIQUE INDEX `collections_path_unique` ON `collections` (`path`);--> statement-breakpoint
28
28
  CREATE TABLE `media` (
29
- `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
29
+ `id` text PRIMARY KEY NOT NULL,
30
30
  `post_id` integer,
31
31
  `filename` text NOT NULL,
32
32
  `original_name` text NOT NULL,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "6",
3
3
  "dialect": "sqlite",
4
- "id": "d32a99d8-a262-45b7-99e4-bc81bbb6f305",
4
+ "id": "3d04f8ef-088d-43f4-9fe9-55ffa2d7a73f",
5
5
  "prevId": "00000000-0000-0000-0000-000000000000",
6
6
  "tables": {
7
7
  "account": {
@@ -125,11 +125,11 @@
125
125
  "notNull": true,
126
126
  "autoincrement": true
127
127
  },
128
- "slug": {
129
- "name": "slug",
128
+ "path": {
129
+ "name": "path",
130
130
  "type": "text",
131
131
  "primaryKey": false,
132
- "notNull": true,
132
+ "notNull": false,
133
133
  "autoincrement": false
134
134
  },
135
135
  "title": {
@@ -162,9 +162,9 @@
162
162
  }
163
163
  },
164
164
  "indexes": {
165
- "collections_slug_unique": {
166
- "name": "collections_slug_unique",
167
- "columns": ["slug"],
165
+ "collections_path_unique": {
166
+ "name": "collections_path_unique",
167
+ "columns": ["path"],
168
168
  "isUnique": true
169
169
  }
170
170
  },
@@ -178,10 +178,10 @@
178
178
  "columns": {
179
179
  "id": {
180
180
  "name": "id",
181
- "type": "integer",
181
+ "type": "text",
182
182
  "primaryKey": true,
183
183
  "notNull": true,
184
- "autoincrement": true
184
+ "autoincrement": false
185
185
  },
186
186
  "post_id": {
187
187
  "name": "post_id",
@@ -5,36 +5,8 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "6",
8
- "when": 1769858252020,
9
- "tag": "0000_solid_moon_knight",
10
- "breakpoints": true
11
- },
12
- {
13
- "idx": 1,
14
- "version": "6",
15
- "when": 1769859000000,
16
- "tag": "0001_add_search_fts",
17
- "breakpoints": true
18
- },
19
- {
20
- "idx": 2,
21
- "version": "6",
22
- "when": 1769860000000,
23
- "tag": "0002_collection_path",
24
- "breakpoints": true
25
- },
26
- {
27
- "idx": 3,
28
- "version": "6",
29
- "when": 1769861000000,
30
- "tag": "0003_collection_path_nullable",
31
- "breakpoints": true
32
- },
33
- {
34
- "idx": 4,
35
- "version": "6",
36
- "when": 1770024000000,
37
- "tag": "0004_media_uuid",
8
+ "when": 1770564499811,
9
+ "tag": "0000_square_wallflower",
38
10
  "breakpoints": true
39
11
  }
40
12
  ]
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@25.1.0_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules/vite/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/vite@7.3.1_@types+node@22.19.10_jiti@2.6.1_lightningcss@1.30.2_tsx@4.21.0_yaml@2.8.2/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../wrangler/bin/wrangler.js" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.61.1_@cloudflare+workers-types@4.20260131.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/bin/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules/wrangler/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/wrangler@4.63.0_@cloudflare+workers-types@4.20260207.0/node_modules:/home/runner/work/jant/jant/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../wrangler/bin/wrangler.js" "$@"
@@ -13,7 +13,8 @@
13
13
  "typecheck": "tsc --noEmit",
14
14
  "db:migrate:local": "wrangler d1 migrations apply DB --local",
15
15
  "db:migrate:remote": "wrangler d1 migrations apply DB --remote",
16
- "jant": "jant"
16
+ "jant": "jant",
17
+ "reset-password": "node scripts/reset-password.mjs"
17
18
  },
18
19
  "dependencies": {
19
20
  "@jant/core": "workspace:*"
@@ -24,6 +25,7 @@
24
25
  "@lingui/swc-plugin": "^5.10.1",
25
26
  "@swc/core": "^1.15.11",
26
27
  "@tailwindcss/vite": "^4.1.18",
28
+ "@types/node": "^22.15.4",
27
29
  "tailwindcss": "^4.1.18",
28
30
  "typescript": "^5.9.3",
29
31
  "unplugin-swc": "^1.5.9",
@@ -0,0 +1,20 @@
1
+ import { randomBytes } from "crypto";
2
+ import { execSync } from "child_process";
3
+
4
+ const isRemote = process.argv.includes("--remote");
5
+ const flag = isRemote ? "--remote" : "--local";
6
+
7
+ const token = randomBytes(32).toString("hex");
8
+ const expiry = Math.floor(Date.now() / 1000) + 15 * 60; // 15 minutes
9
+ const value = `${token}:${expiry}`;
10
+ const timestamp = Math.floor(Date.now() / 1000);
11
+
12
+ const sql = `INSERT OR REPLACE INTO settings (key, value, updated_at) VALUES ('PASSWORD_RESET_TOKEN', '${value}', ${timestamp})`;
13
+
14
+ execSync(`npx wrangler d1 execute DB ${flag} --command "${sql}"`, {
15
+ stdio: "inherit",
16
+ });
17
+
18
+ console.log("");
19
+ console.log("Password reset token generated (expires in 15 minutes).");
20
+ console.log(`Visit: /reset?token=${token}`);
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": [
7
+ "ES2022"
8
+ ],
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "noEmit": true,
12
+ "esModuleInterop": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "verbatimModuleSyntax": true,
16
+ "noUncheckedIndexedAccess": true,
17
+ "noImplicitOverride": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "jsx": "react-jsx",
20
+ "jsxImportSource": "hono/jsx",
21
+ "types": [
22
+ "@cloudflare/workers-types",
23
+ "vite/client"
24
+ ]
25
+ },
26
+ "include": [
27
+ "src/**/*"
28
+ ]
29
+ }
@@ -1,39 +1,7 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "lib": [
7
- "ES2022"
8
- ],
9
- "strict": true,
10
- "skipLibCheck": true,
11
- "noEmit": true,
12
- "esModuleInterop": true,
13
- "resolveJsonModule": true,
14
- "isolatedModules": true,
15
- "verbatimModuleSyntax": true,
16
- "noUncheckedIndexedAccess": true,
17
- "noImplicitOverride": true,
18
- "forceConsistentCasingInFileNames": true,
19
- "jsx": "react-jsx",
20
- "jsxImportSource": "hono/jsx",
21
- "types": [
22
- "@cloudflare/workers-types",
23
- "vite/client"
24
- ],
25
- "paths": {
26
- "@/*": [
27
- "./src/*"
28
- ]
29
- }
30
- },
31
- "include": [
32
- "src/**/*",
33
- "vite.config.ts"
34
- ],
35
- "exclude": [
36
- "node_modules",
37
- "dist"
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
38
6
  ]
39
7
  }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "noEmit": true,
10
+ "esModuleInterop": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "verbatimModuleSyntax": true,
14
+ "noUncheckedIndexedAccess": true,
15
+ "noImplicitOverride": true,
16
+ "forceConsistentCasingInFileNames": true,
17
+ "types": ["@types/node"]
18
+ },
19
+ "include": ["vite.config.ts"]
20
+ }
@@ -38,7 +38,11 @@ function injectManifest(): Plugin {
38
38
  const sentinel = '"__VITE_MANIFEST_CONTENT__"';
39
39
 
40
40
  function readManifest(): string | undefined {
41
- const manifestPath = resolve(process.cwd(), clientOutDir, ".vite/manifest.json");
41
+ const manifestPath = resolve(
42
+ process.cwd(),
43
+ clientOutDir,
44
+ ".vite/manifest.json",
45
+ );
42
46
  try {
43
47
  return readFileSync(manifestPath, "utf-8");
44
48
  } catch {
@@ -54,7 +58,8 @@ function injectManifest(): Plugin {
54
58
  name: "inject-manifest",
55
59
  config(config) {
56
60
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
- clientOutDir = (config as any).environments?.client?.build?.outDir ?? "dist/client";
61
+ clientOutDir =
62
+ (config as any).environments?.client?.build?.outDir ?? "dist/client";
58
63
  },
59
64
 
60
65
  // 1. Try during transform (works when previous client build exists on disk)
@@ -67,7 +72,7 @@ function injectManifest(): Plugin {
67
72
 
68
73
  const newCode = code.replace(
69
74
  /"__VITE_MANIFEST_CONTENT__"/g,
70
- buildReplacement(manifestContent)
75
+ buildReplacement(manifestContent),
71
76
  );
72
77
 
73
78
  if (newCode !== code) {
@@ -188,8 +193,18 @@ export default defineConfig({
188
193
 
189
194
  resolve: {
190
195
  alias: {
191
- "@": "/src",
192
196
  // @monorepo-only-start
197
+ // Monorepo development aliases
198
+ // - @lingui/react/macro: Prevents Vite dependency scan error. Source code imports
199
+ // from @lingui/react/macro (for SWC plugin), but we use Hono JSX. SWC rewrites
200
+ // these at compile time, but Vite scans before SWC runs.
201
+ // - @jant/core: Points to source for HMR during development.
202
+ // Note: User projects don't need @lingui/react/macro alias because they use
203
+ // node_modules/@jant/core/dist/ (already compiled by SWC, imports rewritten).
204
+ "@lingui/react/macro": resolve(
205
+ __dirname,
206
+ "../../packages/core/src/i18n/index.ts",
207
+ ),
193
208
  "@jant/core": resolve(__dirname, "../../packages/core/src"),
194
209
  // @monorepo-only-end
195
210
  },
@@ -6,9 +6,37 @@ compatibility_flags = ["nodejs_compat"]
6
6
  [dev]
7
7
  port = 9019
8
8
 
9
+ # ============================================
10
+ # Environment Variables
11
+ # ============================================
12
+ # Non-sensitive configuration goes here in [vars]
13
+ # Sensitive secrets (like AUTH_SECRET) should be:
14
+ # - Local dev: .dev.vars file (not committed)
15
+ # - Production: wrangler secret put AUTH_SECRET
16
+ # See docs/configuration.md for full details
17
+
9
18
  [vars]
19
+ # Required: Your site's public URL
10
20
  SITE_URL = "http://localhost:9019"
11
21
 
22
+ # Optional: Site configuration
23
+ # These can be overridden in dashboard settings (/dash/settings)
24
+ # If not set, values from database settings table are used
25
+ SITE_NAME = "My Blog 2"
26
+ # SITE_DESCRIPTION = "A personal blog powered by Jant"
27
+ # SITE_LANGUAGE = "en"
28
+
29
+ # Optional: R2 Storage (for media uploads)
30
+ # R2_PUBLIC_URL = "https://cdn.example.com"
31
+
32
+ # Optional: Cloudflare Image Transformations
33
+ # For automatic thumbnail generation and image optimization
34
+ # IMAGE_TRANSFORM_URL = "https://example.com/cdn-cgi/image"
35
+
36
+ # Optional: Demo mode (pre-fill sign-in credentials)
37
+ # DEMO_EMAIL = "demo@example.com"
38
+ # DEMO_PASSWORD = "demo123"
39
+
12
40
  [[d1_databases]]
13
41
  binding = "DB"
14
42
  database_name = "jant-site-db"
@@ -1,40 +0,0 @@
1
- -- FTS5 Full-Text Search for posts
2
- -- This creates a virtual table that indexes post titles and content
3
-
4
- CREATE VIRTUAL TABLE IF NOT EXISTS posts_fts USING fts5(
5
- title,
6
- content,
7
- content='posts',
8
- content_rowid='id'
9
- );
10
- --> statement-breakpoint
11
-
12
- -- Populate FTS table with existing posts
13
- INSERT INTO posts_fts(rowid, title, content)
14
- SELECT id, COALESCE(title, ''), COALESCE(content, '') FROM posts WHERE deleted_at IS NULL;
15
- --> statement-breakpoint
16
-
17
- -- Trigger to keep FTS in sync on INSERT
18
- CREATE TRIGGER posts_fts_insert AFTER INSERT ON posts
19
- WHEN NEW.deleted_at IS NULL
20
- BEGIN
21
- INSERT INTO posts_fts(rowid, title, content)
22
- VALUES (NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.content, ''));
23
- END;
24
- --> statement-breakpoint
25
-
26
- -- Trigger to keep FTS in sync on UPDATE
27
- CREATE TRIGGER posts_fts_update AFTER UPDATE ON posts
28
- BEGIN
29
- DELETE FROM posts_fts WHERE rowid = OLD.id;
30
- INSERT INTO posts_fts(rowid, title, content)
31
- SELECT NEW.id, COALESCE(NEW.title, ''), COALESCE(NEW.content, '')
32
- WHERE NEW.deleted_at IS NULL;
33
- END;
34
- --> statement-breakpoint
35
-
36
- -- Trigger to remove from FTS on DELETE
37
- CREATE TRIGGER posts_fts_delete AFTER DELETE ON posts
38
- BEGIN
39
- DELETE FROM posts_fts WHERE rowid = OLD.id;
40
- END;
@@ -1,2 +0,0 @@
1
- -- Rename slug to path in collections table
2
- ALTER TABLE collections RENAME COLUMN slug TO path;
@@ -1,21 +0,0 @@
1
- -- Make collections.path nullable
2
- -- SQLite doesn't support ALTER COLUMN, so we need to recreate the table
3
-
4
- PRAGMA foreign_keys=OFF;
5
-
6
- CREATE TABLE collections_new (
7
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
8
- path TEXT UNIQUE,
9
- title TEXT NOT NULL,
10
- description TEXT,
11
- created_at INTEGER NOT NULL,
12
- updated_at INTEGER NOT NULL
13
- );
14
-
15
- INSERT INTO collections_new SELECT * FROM collections;
16
-
17
- DROP TABLE collections;
18
-
19
- ALTER TABLE collections_new RENAME TO collections;
20
-
21
- PRAGMA foreign_keys=ON;
@@ -1,35 +0,0 @@
1
- -- Migration: Change media.id from integer to UUIDv7 (text)
2
- -- SQLite doesn't support altering primary key types, so we recreate the table
3
-
4
- -- Create new table with text id
5
- CREATE TABLE media_new (
6
- id TEXT PRIMARY KEY NOT NULL,
7
- post_id INTEGER REFERENCES posts(id),
8
- filename TEXT NOT NULL,
9
- original_name TEXT NOT NULL,
10
- mime_type TEXT NOT NULL,
11
- size INTEGER NOT NULL,
12
- r2_key TEXT NOT NULL,
13
- width INTEGER,
14
- height INTEGER,
15
- alt TEXT,
16
- created_at INTEGER NOT NULL
17
- );
18
-
19
- -- Migrate existing data (generate UUIDv7-like ids from old integer ids)
20
- -- For existing data, we use a deterministic format based on timestamp + old id
21
- INSERT INTO media_new (id, post_id, filename, original_name, mime_type, size, r2_key, width, height, alt, created_at)
22
- SELECT
23
- printf('%08x-%04x-7%03x-%04x-%012x',
24
- created_at,
25
- (id >> 16) & 0xFFFF,
26
- id & 0x0FFF,
27
- 0x8000 | (RANDOM() & 0x3FFF),
28
- ABS(RANDOM())
29
- ) as id,
30
- post_id, filename, original_name, mime_type, size, r2_key, width, height, alt, created_at
31
- FROM media;
32
-
33
- -- Drop old table and rename new one
34
- DROP TABLE media;
35
- ALTER TABLE media_new RENAME TO media;