create-jant 0.3.37 → 0.3.39

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.
Files changed (50) hide show
  1. package/LICENSE +189 -189
  2. package/README.md +8 -6
  3. package/dist/index.js +5 -1
  4. package/package.json +3 -3
  5. package/template/.env.example +21 -0
  6. package/template/README.md +25 -18
  7. package/template/docs/internal/migrate.md +10 -0
  8. package/template/docs/internal/operations.md +61 -0
  9. package/template/package.json +3 -3
  10. package/template/static-site-export/README.md +70 -0
  11. package/template/static-site-export/config.toml +16 -0
  12. package/template/static-site-export/content/41q27/index.md +29 -0
  13. package/template/static-site-export/content/_index.md +4 -0
  14. package/template/static-site-export/content/a-night-heron-field-guide-for-my-walk-folder/index.md +16 -0
  15. package/template/static-site-export/content/a-quiet-saturday-after-a-busy-week/index.md +23 -0
  16. package/template/static-site-export/content/are-na-is-the-only-bookmark-pile-i-still-revisit/index.md +16 -0
  17. package/template/static-site-export/content/bought-too-many-lemons-again/index.md +15 -0
  18. package/template/static-site-export/content/current-tea-rotation/index.md +20 -0
  19. package/template/static-site-export/content/derek-sivers-still-writes-the-kind-of-internet-i-want-more-of/index.md +16 -0
  20. package/template/static-site-export/content/desk-but-better/index.md +16 -0
  21. package/template/static-site-export/content/e0kcg/index.md +12 -0
  22. package/template/static-site-export/content/from-basho/index.md +15 -0
  23. package/template/static-site-export/content/from-epictetus/index.md +15 -0
  24. package/template/static-site-export/content/from-marcus-aurelius/index.md +15 -0
  25. package/template/static-site-export/content/from-seneca/index.md +15 -0
  26. package/template/static-site-export/content/from-thoreau/index.md +15 -0
  27. package/template/static-site-export/content/gkbvv/index.md +28 -0
  28. package/template/static-site-export/content/k5vh8/index.md +29 -0
  29. package/template/static-site-export/content/mynoise-for-rainy-afternoons/index.md +16 -0
  30. package/template/static-site-export/content/nts-archives-are-good-cleaning-music/index.md +16 -0
  31. package/template/static-site-export/content/qgfcu/index.md +29 -0
  32. package/template/static-site-export/content/rain-makes-my-neighborhood-look-better/index.md +17 -0
  33. package/template/static-site-export/content/serious-eats-on-tomato-and-egg-soup/index.md +16 -0
  34. package/template/static-site-export/content/te812/index.md +29 -0
  35. package/template/static-site-export/content/telk3/index.md +29 -0
  36. package/template/static-site-export/content/the-five-minute-reset-is-still-the-best-habit-i-have/index.md +21 -0
  37. package/template/static-site-export/content/the-hallway-light-took-12-minutes-and-3-months/index.md +18 -0
  38. package/template/static-site-export/content/the-recurse-center-manual-is-weirdly-calming/index.md +16 -0
  39. package/template/static-site-export/content/u08bn/index.md +29 -0
  40. package/template/static-site-export/content/what-i-actually-use-my-notebook-for/index.md +23 -0
  41. package/template/static-site-export/content/z4s9v/index.md +29 -0
  42. package/template/static-site-export/static/style.css +338 -0
  43. package/template/static-site-export/templates/base.html +23 -0
  44. package/template/static-site-export/templates/index.html +20 -0
  45. package/template/static-site-export/templates/macros.html +58 -0
  46. package/template/static-site-export/templates/page.html +8 -0
  47. package/template/static-site-export/templates/section.html +17 -0
  48. package/template/static-site-export/templates/taxonomy_list.html +15 -0
  49. package/template/static-site-export/templates/taxonomy_single.html +13 -0
  50. package/template/wrangler.toml +12 -7
package/README.md CHANGED
@@ -45,7 +45,9 @@ cp .dev.vars.example .dev.vars
45
45
  pnpm dev
46
46
  ```
47
47
 
48
- Visit http://localhost:9020 to see your site.
48
+ Visit http://localhost:3000 to see your site.
49
+
50
+ Need another local port? Run `PORT=3030 pnpm dev`.
49
51
 
50
52
  ## Project Structure
51
53
 
@@ -71,18 +73,18 @@ my-site/
71
73
  ## Scripts
72
74
 
73
75
  ```bash
74
- pnpm dev # Start dev server (http://localhost:9020)
76
+ pnpm dev # Start dev server (http://localhost:3000)
75
77
  pnpm build # Build for production
76
- pnpm run deploy # Build + deploy to Cloudflare Workers
78
+ pnpm run deploy # Apply migrations/backfills and deploy to Cloudflare Workers
77
79
  pnpm typecheck # Run TypeScript checks
78
80
  pnpm lint # Run ESLint
79
81
  pnpm format # Format code with Prettier
80
82
  pnpm db:generate # Generate Drizzle migrations
81
- pnpm db:migrate:local # Apply migrations (local)
82
- pnpm db:migrate:remote # Apply migrations (production)
83
+ pnpm exec jant migrate --local # Apply schema migrations + data backfills (local)
84
+ pnpm exec jant migrate --remote # Apply schema migrations + data backfills (production)
83
85
  pnpm i18n:build # Extract + compile translations
84
86
  ```
85
87
 
86
88
  ## License
87
89
 
88
- AGPL-3.0
90
+ AGPL-3.0-or-later
package/dist/index.js CHANGED
@@ -9,7 +9,8 @@ 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.37";
12
+ var CORE_VERSION = "0.3.39";
13
+ var WRANGLER_VERSION = "^4.76.0";
13
14
  var TEMPLATE_DIR = fs.existsSync(path.resolve(__dirname, "../template")) ? path.resolve(__dirname, "../template") : path.resolve(__dirname, "../../../sites/demo");
14
15
  function isValidProjectName(name) {
15
16
  return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(name);
@@ -114,6 +115,9 @@ async function copyTemplate(config) {
114
115
  if (pkg.dependencies?.["@jant/core"] === "workspace:*") {
115
116
  pkg.dependencies["@jant/core"] = `^${CORE_VERSION}`;
116
117
  }
118
+ if (pkg.devDependencies?.wrangler === "catalog:") {
119
+ pkg.devDependencies.wrangler = WRANGLER_VERSION;
120
+ }
117
121
  if (packageManager !== "pnpm" && pkg.scripts) {
118
122
  delete pkg.packageManager;
119
123
  for (const [key, value] of Object.entries(pkg.scripts)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jant",
3
- "version": "0.3.37",
3
+ "version": "0.3.39",
4
4
  "description": "Create a new Jant project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,7 +45,7 @@
45
45
  "workers",
46
46
  "hono"
47
47
  ],
48
- "license": "AGPL-3.0",
48
+ "license": "AGPL-3.0-or-later",
49
49
  "publishConfig": {
50
50
  "access": "public"
51
51
  },
@@ -54,7 +54,7 @@
54
54
  "dev": "tsup src/index.ts --format esm --watch",
55
55
  "typecheck": "tsc --noEmit",
56
56
  "copy-template": "rm -rf template && rsync -a --exclude node_modules --exclude .wrangler --exclude .dev.vars --exclude scripts ../../sites/demo/ template/ && mv template/.gitignore template/_gitignore && mv template/.github template/_github",
57
- "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))\"",
57
+ "inject-version": "node -e \"const fs=require('fs');const path=require('path');const coreVersion=require('../core/package.json').version;const workspace=fs.readFileSync(path.resolve(__dirname,'../../pnpm-workspace.yaml'),'utf8');const match=workspace.match(/^[ \\t]*wrangler:[ \\t]*(.+)$/m);if(!match)throw new Error('Unable to resolve wrangler catalog version');const wranglerVersion=match[1].trim();const f='dist/index.js';const source=fs.readFileSync(f,'utf8').replace('__JANT_CORE_VERSION__',coreVersion).replace('__WRANGLER_VERSION__',wranglerVersion);fs.writeFileSync(f,source)\"",
58
58
  "test-template": "node scripts/test-template.js"
59
59
  }
60
60
  }
@@ -0,0 +1,21 @@
1
+ # Repo-level demo-public automation overrides.
2
+ #
3
+ # These files are only consumed by the repo's demo scripts and mise tasks.
4
+ # Shell environment variables still win over file values.
5
+ #
6
+ # Put shared Cloudflare credentials in the repo root `.env.repo.local`
7
+ # or `.env.repo`:
8
+ # CLOUDFLARE_API_TOKEN=...
9
+ # CLOUDFLARE_ACCOUNT_ID=...
10
+
11
+ # Optional: override the public demo URL without editing wrangler.toml.
12
+ # DEMO_PUBLIC_URL=https://demo.jant.me
13
+
14
+ # Required for repo tasks that call demo-public internal maintenance endpoints.
15
+ # Set the same value as a Worker secret on the deployed demo site:
16
+ # wrangler secret put INTERNAL_ADMIN_TOKEN
17
+ INTERNAL_ADMIN_TOKEN=replace_with_a_long_random_secret
18
+
19
+ # Optional: override the managed demo login used by bootstrap-demo.mjs.
20
+ # DEMO_EMAIL=demo@jant.me
21
+ # DEMO_PASSWORD=jantdemodemojant
@@ -10,21 +10,22 @@ Deploy to Cloudflare instantly — no local setup required:
10
10
 
11
11
  ### Deploy form fields
12
12
 
13
- | Field | What to do |
14
- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
- | **Git account** | Select your GitHub account. A new repo will be created for you. |
16
- | **D1 database** | Keep "Create new". The default name is fine. |
17
- | **Database location hint** | Pick a region close to you (optional, Cloudflare auto-selects). |
18
- | **R2 bucket** | Keep "Create new". The default name is fine. Used for media uploads. |
19
- | **AUTH_SECRET** | Used for login session encryption. Keep the pre-filled value or generate your own with `openssl rand -base64 32`. |
20
- | **SITE_URL** | Change this to your production URL (e.g. `https://my-blog.example.com`). If you don't have a custom domain yet, leave it empty you can set it later in the Cloudflare dashboard after you know your `*.workers.dev` URL. |
13
+ | Field | What to do |
14
+ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
+ | **Git account** | Select your GitHub account. A new repo will be created for you. |
16
+ | **D1 database** | Keep "Create new". The default name is fine. |
17
+ | **Database location hint** | Pick a region close to you (optional, Cloudflare auto-selects). |
18
+ | **R2 bucket** | Keep "Create new". The default name is fine. Used for media uploads. |
19
+ | **AUTH_SECRET** | Used for login session encryption. Keep the pre-filled value or generate your own with `openssl rand -base64 32`. |
20
+ | **SITE_ORIGIN** | Optional. Set this when you want a fixed public origin such as `https://my-blog.example.com`. If you leave it empty, Jant uses the current request origin. |
21
+ | **SITE_PATH_PREFIX** | Optional. Set this only when you mount the site under a subpath such as `/blog`. Leave it empty for normal root deploys. |
21
22
 
22
23
  ### After deploy
23
24
 
24
25
  1. Visit your site at the URL shown in the Cloudflare dashboard (e.g. `https://<project>.<account>.workers.dev`)
25
26
  2. Go to `/setup` to set up your admin account
26
- 3. If you set `SITE_URL` to a custom domain, add it in: Cloudflare dashboard → Workers & Pages → your worker → Settings → Domains & Routes → Add Custom Domain
27
- 4. If you left `SITE_URL` empty, set it to your `*.workers.dev` URL: Cloudflare dashboard Workers & Pages → your worker → Settings → Variables and Secrets
27
+ 3. If you set `SITE_ORIGIN` to a custom domain, add it in: Cloudflare dashboard → Workers & Pages → your worker → Settings → Domains & Routes → Add Custom Domain
28
+ 4. If you leave `SITE_ORIGIN` empty, Jant uses your current `*.workers.dev` or custom-domain request host automatically
28
29
 
29
30
  ### Develop locally
30
31
 
@@ -36,7 +37,7 @@ npm install
36
37
  npm run dev
37
38
  ```
38
39
 
39
- Visit http://localhost:8787. Changes pushed to `main` will auto-deploy.
40
+ Visit http://localhost:3000. Changes pushed to `main` will auto-deploy.
40
41
 
41
42
  ## Option B: Create with CLI
42
43
 
@@ -48,7 +49,9 @@ cd my-site
48
49
  npm run dev
49
50
  ```
50
51
 
51
- Visit http://localhost:8787. When you're ready to go live, continue with [Deploy to Cloudflare](#deploy-to-cloudflare) below.
52
+ Visit http://localhost:3000. When you're ready to go live, continue with [Deploy to Cloudflare](#deploy-to-cloudflare) below.
53
+
54
+ Need another local port? Run `PORT=3030 npm run dev`.
52
55
 
53
56
  ### Deploy to Cloudflare
54
57
 
@@ -74,11 +77,14 @@ wrangler d1 create <your-project>-db
74
77
  Edit `wrangler.toml`:
75
78
 
76
79
  - Replace `database_id = "local"` with the ID from step 2
77
- - Set `SITE_URL` to your production URL (e.g. `https://example.com`)
80
+ - Set `SITE_ORIGIN` if you want a fixed public origin (e.g. `https://example.com`)
81
+ - Set `SITE_PATH_PREFIX` only if you deploy under a subpath (e.g. `/blog`)
78
82
 
79
83
  > R2 bucket is automatically created on first deploy — no manual setup needed.
80
84
  >
81
85
  > **Note:** Changing `database_id` resets your local development database (local data is stored per database ID). If you've already started local development, you'll need to go through the setup wizard again to create your admin account.
86
+ >
87
+ > **Subpath deploys on Cloudflare:** If `SITE_PATH_PREFIX` is set to `/blog`, Jant publishes built assets under `/blog/_assets/*`. `npm run deploy` detects that prefix and prepares `dist/public/blog/_assets/*` automatically, so routing `/blog*` to the same Worker is enough.
82
88
 
83
89
  #### 4. Set Production Secrets
84
90
 
@@ -165,7 +171,7 @@ The workflow is pre-configured to deploy on every push to `main`. After pushing
165
171
  | Command | Description |
166
172
  | ------------------------ | ------------------------------------------------ |
167
173
  | `npm run dev` | Start local dev server (auto-applies migrations) |
168
- | `npm run deploy` | Apply remote migrations, build, and deploy |
174
+ | `npm run deploy` | Apply remote migrations and deploy |
169
175
  | `npm run reset-password` | Generate a password reset link if locked out |
170
176
  | `npm run export` | Export D1 database to a SQL file |
171
177
 
@@ -173,10 +179,11 @@ The workflow is pre-configured to deploy on every push to `main`. After pushing
173
179
 
174
180
  ## Environment Variables
175
181
 
176
- | Variable | Description | Location |
177
- | ------------- | ----------------------------------------- | ---------------- |
178
- | `AUTH_SECRET` | Secret key for authentication (32+ chars) | `.dev.vars` file |
179
- | `SITE_URL` | Your site's public URL | `wrangler.toml` |
182
+ | Variable | Description | Location |
183
+ | ------------------ | ---------------------------------------------- | ---------------- |
184
+ | `AUTH_SECRET` | Secret key for authentication (32+ chars) | `.dev.vars` file |
185
+ | `SITE_ORIGIN` | Optional fixed public origin for absolute URLs | `wrangler.toml` |
186
+ | `SITE_PATH_PREFIX` | Optional public path prefix such as `/blog` | `wrangler.toml` |
180
187
 
181
188
  For all available variables (site name, language, R2 storage, image optimization, S3, demo mode, etc.), see the **[Configuration Guide](https://github.com/jant-me/jant/blob/main/docs/configuration.md)**.
182
189
 
@@ -0,0 +1,10 @@
1
+ # Demo Public Migration
2
+
3
+ ```
4
+ mise run demo-public-rebuild
5
+ ```
6
+
7
+ This is the canonical rebuild path for `demo.jant.me`. It imports the committed
8
+ snapshot from `sites/demo-source/canonical/snapshot/`.
9
+
10
+ See `sites/demo/docs/internal/operations.md` for the full public-demo workflow.
@@ -0,0 +1,61 @@
1
+ # Demo Public Operations
2
+
3
+ `sites/demo` is the public demo runtime at `demo.jant.me`.
4
+
5
+ The daily operational commands still live in the root `mise.toml` because the
6
+ workflow crosses both `sites/demo-source` and `sites/demo`, and `sites/demo`
7
+ also doubles as the starter template source.
8
+
9
+ ## Common Commands
10
+
11
+ ```sh
12
+ mise run demo-public-bootstrap
13
+ mise run demo-public-rebuild
14
+ mise run demo-public-verify
15
+ mise run demo-public-clear-content
16
+ mise run demo-public-clear-api-tokens
17
+ ```
18
+
19
+ ## Environment Files for Repo Tasks
20
+
21
+ Repo-level demo tasks now auto-load:
22
+
23
+ 1. `sites/demo/.env.local`
24
+ 2. `sites/demo/.env`
25
+ 3. repo root `.env.repo.local`
26
+ 4. repo root `.env.repo`
27
+ 5. legacy repo root `.env.local`
28
+ 6. legacy repo root `.env`
29
+
30
+ Shell environment variables still win over all of them.
31
+
32
+ Recommended split:
33
+
34
+ - repo root `.env.repo.local`: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`
35
+ Start from [/.env.repo.example](/Users/green/project/jant/main/.env.repo.example).
36
+ - [`sites/demo/.env.example`](/Users/green/project/jant/main/sites/demo/.env.example):
37
+ copy to `.env.local` for `INTERNAL_ADMIN_TOKEN`, plus any local
38
+ overrides such as `DEMO_PUBLIC_URL`, `DEMO_EMAIL`, or `DEMO_PASSWORD`
39
+
40
+ ## Expected Flow
41
+
42
+ 1. Curate content in `demo-source`.
43
+ 2. Freeze it with `mise run demo-source-export-canonical`.
44
+ 3. Review and commit `sites/demo-source/canonical/snapshot/`.
45
+ 4. Publish it to `demo-public` with `mise run demo-public-rebuild`.
46
+ 5. Let `.github/workflows/reset-demo.yml` re-run the same rebuild nightly.
47
+
48
+ ## Notes
49
+
50
+ - `demo-public-rebuild` is snapshot-based. It no longer imports the old static
51
+ site export.
52
+ - `demo-public-rebuild` keeps a standalone storage cleanup step before import.
53
+ That cleanup exists so demo maintenance can enforce its own storage policy
54
+ separately from the normal snapshot restore contract.
55
+ - `demo-public-rebuild` also clears every user-created API token through
56
+ `INTERNAL_ADMIN_TOKEN`, so demo tokens are disposable across nightly
57
+ resets.
58
+ - The rebuild workflow still imports the canonical snapshot with an explicit
59
+ remap intent rather than relying on implicit single-site behavior.
60
+ - `db-demo-reseed` remains as a compatibility alias for
61
+ `mise run demo-public-rebuild`.
@@ -3,8 +3,8 @@
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "scripts": {
6
- "dev": "echo y | wrangler d1 migrations apply DB --local && wrangler dev",
7
- "deploy": "wrangler d1 migrations apply DB --remote && wrangler deploy",
6
+ "dev": "jant migrate --local && node scripts/dev.mjs",
7
+ "deploy": "node ../../scripts/demo-shared/run-with-env.mjs --site demo -- pnpm exec jant deploy",
8
8
  "reset-password": "jant reset-password",
9
9
  "export": "jant export"
10
10
  },
@@ -12,6 +12,6 @@
12
12
  "@jant/core": "workspace:*"
13
13
  },
14
14
  "devDependencies": {
15
- "wrangler": "^4.61.1"
15
+ "wrangler": "^4.76.0"
16
16
  }
17
17
  }
@@ -0,0 +1,70 @@
1
+ # Jant Demo — Zola Export
2
+
3
+ This is a static site exported from [Jant](https://github.com/jant-me/jant), ready to build with [Zola](https://www.getzola.org/).
4
+
5
+ ## Install Zola
6
+
7
+ **macOS (Homebrew):**
8
+
9
+ ```sh
10
+ brew install zola
11
+ ```
12
+
13
+ **Windows (Scoop):**
14
+
15
+ ```sh
16
+ scoop install zola
17
+ ```
18
+
19
+ **Linux (Snap):**
20
+
21
+ ```sh
22
+ snap install zola --edge
23
+ ```
24
+
25
+ Or download a binary from <https://github.com/getzola/zola/releases>.
26
+
27
+ See the [Zola installation docs](https://www.getzola.org/documentation/getting-started/installation/) for more options.
28
+
29
+ ## Quick start
30
+
31
+ Preview locally:
32
+
33
+ ```sh
34
+ zola serve
35
+ ```
36
+
37
+ Then open <http://127.0.0.1:1111> in your browser.
38
+
39
+ Build the site for deployment:
40
+
41
+ ```sh
42
+ zola build
43
+ ```
44
+
45
+ The output goes to the `public/` directory. Upload it to any static host (Netlify, Vercel, Cloudflare Pages, GitHub Pages, etc.).
46
+
47
+ ## Project structure
48
+
49
+ ```
50
+ config.toml — Site configuration (title, URL, language)
51
+ content/
52
+ _index.md — Root section (homepage settings)
53
+ {slug}/index.md — Individual posts (threads are merged into one page)
54
+ templates/ — Tera templates (Zola's template engine)
55
+ static/
56
+ style.css — Stylesheet
57
+ ```
58
+
59
+ ## Customizing
60
+
61
+ - **Site settings** — edit `config.toml` to change the title, URL, or language.
62
+ - **Styles** — edit `static/style.css`. The theme supports light and dark modes via `prefers-color-scheme`.
63
+ - **Templates** — edit files in `templates/`. Zola uses the [Tera](https://keats.github.io/tera/) template engine.
64
+ - **Collections** — posts are tagged with collections via the `c` taxonomy. Browse them at `/c/`.
65
+
66
+ ## Notes
67
+
68
+ - Media files (images, etc.) are **not** included in the export. They link back to the original site.
69
+ - Thread replies are merged into the root post as a single page. Reply metadata is preserved in HTML comments (`<!-- jant:reply ... -->`).
70
+ - Posts with `draft: true` in front matter are only built when you pass the `--drafts` flag to `zola build` or `zola serve`.
@@ -0,0 +1,16 @@
1
+ base_url = "https://demo.jant.me/"
2
+ title = "Jant Demo"
3
+ description = "Thoughts, links, and quotes — one post at a time"
4
+ default_language = "en"
5
+ generate_feeds = true
6
+ compile_sass = false
7
+
8
+ [[taxonomies]]
9
+ name = "c"
10
+ feed = true
11
+
12
+ [markdown]
13
+ highlight_code = true
14
+ highlight_theme = "css"
15
+
16
+ [extra]
@@ -0,0 +1,29 @@
1
+ ---
2
+ date: 2025-09-27T08:15:00.000Z
3
+ updated: 2026-03-17T20:15:39.000Z
4
+ slug: 41q27
5
+ aliases:
6
+ - /0x4nv
7
+ - /the-potting-mix-guide-i-keep-rereading
8
+ - /faqyt
9
+ taxonomies:
10
+ c:
11
+ - weekend-notes
12
+ - tiny-projects
13
+ extra:
14
+ format: note
15
+ ---
16
+
17
+ Repotted the balcony herbs before breakfast. Basil was dramatic. Mint did not care at all.
18
+
19
+ <!-- jant:reply date="2025-09-27T09:00:00.000Z" slug="0x4nv" format="note" -->
20
+
21
+ I keep forgetting that plants mostly want consistency, not inspiration. Fair enough.
22
+
23
+ <!-- jant:reply date="2025-09-27T09:40:00.000Z" slug="the-potting-mix-guide-i-keep-rereading" format="link" url="https://www.rhs.org.uk/plants/types/houseplants/repotting" title="The potting mix guide I keep rereading" -->
24
+
25
+ Basic, clear, and good for confidence when I start overthinking dirt.
26
+
27
+ <!-- jant:reply date="2025-09-27T16:50:00.000Z" slug="faqyt" format="note" -->
28
+
29
+ By late afternoon the basil was standing up again. I respect a fast recovery.
@@ -0,0 +1,4 @@
1
+ +++
2
+ sort_by = "date"
3
+ paginate_by = 20
4
+ +++
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: A night heron field guide for my walk folder
3
+ date: 2026-03-05T09:10:00.000Z
4
+ updated: 2026-03-17T20:15:31.000Z
5
+ slug: a-night-heron-field-guide-for-my-walk-folder
6
+ taxonomies:
7
+ c:
8
+ - useful-links
9
+ - city-walks
10
+ extra:
11
+ format: link
12
+ link_url: "https://www.audubon.org/field-guide/bird/black-crowned-night-heron"
13
+ rating: 4
14
+ ---
15
+
16
+ Posting this here so I can find it again the next time I see a suspiciously patient bird near the water.
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: A Quiet Saturday After a Busy Week
3
+ date: 2025-08-03T09:10:00.000Z
4
+ updated: 2026-03-17T20:15:13.000Z
5
+ slug: a-quiet-saturday-after-a-busy-week
6
+ taxonomies:
7
+ c:
8
+ - weekend-notes
9
+ extra:
10
+ format: note
11
+ pinned: true
12
+ featured: true
13
+ ---
14
+
15
+ Last week felt like six weeks compressed into five days. I spent most of it answering things, moving things, and promising myself I would slow down later. Today was the later I had in mind.
16
+
17
+ Breakfast took an hour. I opened the windows even though it was still cold. I put the phone on the bookshelf and left it there long enough to hear the apartment settle down.
18
+
19
+ <!--more-->
20
+
21
+ What helped most was not turning the free day into a project. I made coffee, wiped the kitchen counter, read twenty pages, and sat in the chair by the window without trying to optimize anything.
22
+
23
+ A good day does not always need a headline. Sometimes it only needs enough room to happen.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Are.na is the only bookmark pile I still revisit
3
+ date: 2025-10-15T14:15:00.000Z
4
+ updated: 2026-03-17T20:15:22.000Z
5
+ slug: are-na-is-the-only-bookmark-pile-i-still-revisit
6
+ taxonomies:
7
+ c:
8
+ - useful-links
9
+ - tiny-projects
10
+ extra:
11
+ format: link
12
+ link_url: "https://www.are.na/"
13
+ rating: 4
14
+ ---
15
+
16
+ Most saved links disappear into a hole. This one still feels calm enough to browse on purpose.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Bought Too Many Lemons Again
3
+ date: 2025-11-09T09:20:00.000Z
4
+ updated: 2026-03-17T20:15:25.000Z
5
+ slug: bought-too-many-lemons-again
6
+ taxonomies:
7
+ c:
8
+ - home-cooking
9
+ extra:
10
+ format: note
11
+ ---
12
+
13
+ Came home from the market with a bag of lemons, parsley, eggs, and zero idea what dinner was going to be.
14
+
15
+ This keeps happening. I think part of me believes citrus counts as a plan.
@@ -0,0 +1,20 @@
1
+ ---
2
+ title: Current Tea Rotation
3
+ date: 2025-09-06T09:45:00.000Z
4
+ updated: 2026-03-17T20:15:19.000Z
5
+ slug: current-tea-rotation
6
+ taxonomies:
7
+ c:
8
+ - weekend-notes
9
+ - home-cooking
10
+ extra:
11
+ format: note
12
+ ---
13
+
14
+ The kitchen shelf is doing a lot of work right now.
15
+
16
+ - Jasmine for late afternoons
17
+ - Black tea when I need to become a person quickly
18
+ - Mint tea after dinner when I want the day to stop talking
19
+
20
+ Nothing profound here. I just like having a small system for ordinary comfort.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Derek Sivers still writes the kind of internet I want more of
3
+ date: 2025-11-25T08:50:00.000Z
4
+ updated: 2026-03-17T20:15:24.000Z
5
+ slug: derek-sivers-still-writes-the-kind-of-internet-i-want-more-of
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ - useful-links
10
+ extra:
11
+ format: link
12
+ link_url: "https://sive.rs/"
13
+ rating: 4
14
+ ---
15
+
16
+ Short pages, clear opinions, no inflation. I usually leave with one useful sentence and that is enough.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: "Desk, But Better"
3
+ date: 2026-03-01T10:45:00.000Z
4
+ updated: 2026-03-17T20:15:32.000Z
5
+ slug: desk-but-better
6
+ taxonomies:
7
+ c:
8
+ - tiny-projects
9
+ extra:
10
+ format: note
11
+ pinned: true
12
+ ---
13
+
14
+ I finally made the desk simple enough that I want to sit down there again.
15
+
16
+ The rule is now: laptop, lamp, notebook, water. If something else lives there, it has to earn the space.
@@ -0,0 +1,12 @@
1
+ ---
2
+ date: 2025-08-04T07:25:00.000Z
3
+ updated: 2026-03-17T20:15:14.000Z
4
+ slug: e0kcg
5
+ taxonomies:
6
+ c:
7
+ - weekend-notes
8
+ extra:
9
+ format: note
10
+ ---
11
+
12
+ Opened every window this morning and the whole place smelled like rain, old wood, and somebody else's toast. Good start.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: From Basho
3
+ date: 2025-08-12T08:30:00.000Z
4
+ updated: 2026-03-17T20:15:16.000Z
5
+ slug: from-basho
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ extra:
10
+ format: quote
11
+ link_url: "https://en.wikiquote.org/wiki/Matsuo_Basho"
12
+ quote_text: "Every day is a journey, and the journey itself is home."
13
+ ---
14
+
15
+ I like this more the older I get. It makes errands, walks, and ordinary Tuesdays feel less disposable.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: From Epictetus
3
+ date: 2026-02-05T06:55:00.000Z
4
+ updated: 2026-03-17T20:15:29.000Z
5
+ slug: from-epictetus
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ extra:
10
+ format: quote
11
+ link_url: "https://en.wikiquote.org/wiki/Epictetus"
12
+ quote_text: First say to yourself what you would be; and then do what you have to do.
13
+ ---
14
+
15
+ A little stern, maybe. Still useful on the mornings when I drift too long before starting anything.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: From Marcus Aurelius
3
+ date: 2025-09-03T12:20:00.000Z
4
+ updated: 2026-03-17T20:15:18.000Z
5
+ slug: from-marcus-aurelius
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ extra:
10
+ format: quote
11
+ link_url: "https://en.wikiquote.org/wiki/Marcus_Aurelius"
12
+ quote_text: The art of life is more like wrestling than dancing.
13
+ ---
14
+
15
+ Good sentence for the weeks when nothing arrives in the right order and everything needs a little more effort than expected.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: From Seneca
3
+ date: 2025-12-10T07:35:00.000Z
4
+ updated: 2026-03-17T20:15:26.000Z
5
+ slug: from-seneca
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ extra:
10
+ format: quote
11
+ link_url: "https://en.wikiquote.org/wiki/Seneca_the_Younger"
12
+ quote_text: "While we wait for life, life passes."
13
+ ---
14
+
15
+ Copied this onto a sticky note and left it by the monitor for a week. It did its job.
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: From Thoreau
3
+ date: 2025-10-26T20:10:00.000Z
4
+ updated: 2026-03-17T20:15:23.000Z
5
+ slug: from-thoreau
6
+ taxonomies:
7
+ c:
8
+ - reading-notes
9
+ extra:
10
+ format: quote
11
+ link_url: "https://en.wikiquote.org/wiki/Henry_David_Thoreau"
12
+ quote_text: The price of anything is the amount of life you exchange for it.
13
+ ---
14
+
15
+ Useful line before I buy nonsense online because I had a long day and want to feel rewarded.