Adds a simple updatedAt implementation that follows publishedAt closely. I was also trying to add automatic updatedAt detection but it was proving to be complicated and opinionated
+46
-1
Diff
round #0
+22
-1
packages/cli/src/lib/atproto.ts
+22
-1
packages/cli/src/lib/atproto.ts
···
26
26
typeof v.site === "string" &&
27
27
typeof v.path === "string" &&
28
28
typeof v.textContent === "string" &&
29
-
typeof v.publishedAt === "string"
29
+
typeof v.publishedAt === "string" &&
30
+
(v.updatedAt === undefined || typeof v.updatedAt === "string")
30
31
);
31
32
}
32
33
···
252
253
);
253
254
const publishDate = new Date(post.frontmatter.publishDate);
254
255
256
+
// Handle updatedAt: only set if explicitly provided in frontmatter
257
+
let updatedAt: Date | undefined;
258
+
if (post.frontmatter.updatedAt) {
259
+
updatedAt = new Date(post.frontmatter.updatedAt);
260
+
}
261
+
255
262
// Determine textContent (if enabled): use configured field from frontmatter, or fallback to markdown body
256
263
let textContent: string | null = null;
257
264
if (
···
274
281
canonicalUrl: `${config.siteUrl}${postPath}`,
275
282
};
276
283
284
+
if (updatedAt) {
285
+
record.updatedAt = updatedAt.toISOString();
286
+
}
287
+
277
288
if (post.frontmatter.description) {
278
289
record.description = post.frontmatter.description;
279
290
}
···
318
329
);
319
330
const publishDate = new Date(post.frontmatter.publishDate);
320
331
332
+
// Handle updatedAt: only set if explicitly provided in frontmatter
333
+
let updatedAt = post.frontmatter.updatedAt
334
+
? new Date(post.frontmatter.updatedAt)
335
+
: undefined;
336
+
321
337
// Determine textContent (if enabled): use configured field from frontmatter, or fallback to markdown body
322
338
let textContent: string | null = null;
323
339
if (
···
349
365
canonicalUrl: `${config.siteUrl}${postPath}`,
350
366
};
351
367
368
+
if (updatedAt) {
369
+
record.updatedAt = updatedAt.toISOString();
370
+
}
371
+
352
372
if (post.frontmatter.description) {
353
373
record.description = post.frontmatter.description;
354
374
}
···
388
408
path: string;
389
409
textContent?: string;
390
410
publishedAt: string;
411
+
updatedAt?: string;
391
412
canonicalUrl?: string;
392
413
description?: string;
393
414
coverImage?: BlobObject;
+17
packages/cli/src/lib/markdown.ts
+17
packages/cli/src/lib/markdown.ts
···
75
75
}
76
76
}
77
77
78
+
// Updated date mapping - check custom field first, then fallbacks
79
+
const updatedAtField = mapping?.updatedAt;
80
+
if (updatedAtField && raw[updatedAtField]) {
81
+
frontmatter.updatedAt = raw[updatedAtField];
82
+
} else if (raw.updatedAt) {
83
+
frontmatter.updatedAt = raw.updatedAt;
84
+
} else {
85
+
// Fallback to common date field names
86
+
const updatedAtFields = ["updated_at", "modifiedAt", "modified_at"];
87
+
for (const field of updatedAtFields) {
88
+
if (raw[field]) {
89
+
frontmatter.updatedAt = raw[field];
90
+
break;
91
+
}
92
+
}
93
+
}
94
+
78
95
// Cover image mapping
79
96
const coverField = mapping?.coverImage || "ogImage";
80
97
frontmatter.ogImage = raw[coverField] || raw.ogImage;
+2
packages/cli/src/lib/types.ts
+2
packages/cli/src/lib/types.ts
···
2
2
title?: string; // Field name for title (default: "title")
3
3
description?: string; // Field name for description (default: "description")
4
4
publishDate?: string; // Field name for publish date (default: "publishDate", also checks "pubDate", "date", "createdAt", "created_at")
5
+
updatedAt?: string; // Field name for updated date (default: "updatedAt", also checks "updated_at", "modifiedAt", "modified_at")
5
6
coverImage?: string; // Field name for cover image (default: "ogImage")
6
7
tags?: string; // Field name for tags (default: "tags")
7
8
draft?: string; // Field name for draft status (default: "draft")
···
90
91
description?: string;
91
92
bskyPost?: string;
92
93
publishDate: string;
94
+
updatedAt?: string;
93
95
tags?: string[];
94
96
ogImage?: string;
95
97
atUri?: string;
+5
sequoia.schema.json
+5
sequoia.schema.json
···
70
70
"description": "Field name for publish date (checks \"publishDate\", \"pubDate\", \"date\", \"createdAt\", and \"created_at\" by default)",
71
71
"default": "publishDate"
72
72
},
73
+
"updatedAt": {
74
+
"type": "string",
75
+
"description": "Field name for updated date (checks \"updatedAt\", \"updated_at\", \"modifiedAt\", and \"modified_at\" by default)",
76
+
"default": "updatedAt"
77
+
},
73
78
"coverImage": {
74
79
"type": "string",
75
80
"description": "Field name for cover image",
Nice!! Thank you for this ๐