feat: add option to disable publishing (text) content 594cd435
Willow (GHOST) · 2026-03-06 05:40 6 file(s) · +40 −10
packages/cli/src/commands/init.ts +6 −0
98 98
						message: "URL path prefix for posts:",
99 99
						placeholder: "/posts, /blog, /articles, etc.",
100 100
					}),
101 +
				publishContent: () =>
102 +
					confirm({
103 +
						message: "Publish the post content on the standard.site document?",
104 +
						initialValue: true,
105 +
					}),
101 106
			},
102 107
			{ onCancel },
103 108
		);
341 346
			pdsUrl,
342 347
			frontmatter: frontmatterMapping,
343 348
			bluesky: blueskyConfig,
349 +
			publishContent: siteConfig.publishContent,
344 350
		});
345 351
346 352
		const configPath = path.join(process.cwd(), "sequoia.json");
packages/cli/src/commands/update.ts +9 −0
162 162
			stripDatePrefix: configUpdated.stripDatePrefix,
163 163
			pathTemplate: configUpdated.pathTemplate,
164 164
			textContentField: configUpdated.textContentField,
165 +
			publishContent: configUpdated.publishContent,
165 166
			bluesky: configUpdated.bluesky,
166 167
		});
167 168
373 374
		}),
374 375
	);
375 376
377 +
	const publishContent = exitOnCancel(
378 +
		await confirm({
379 +
			message: "Publish the post content on the standard.site document?",
380 +
			initialValue: config.publishContent ?? true,
381 +
		}),
382 +
	);
383 +
376 384
	const textContentField = exitOnCancel(
377 385
		await text({
378 386
			message:
397 405
		removeIndexFromSlug: removeIndexFromSlug || undefined,
398 406
		stripDatePrefix: stripDatePrefix || undefined,
399 407
		textContentField: textContentField || undefined,
408 +
		publishContent: publishContent ?? true,
400 409
	};
401 410
}
402 411
packages/cli/src/lib/atproto.ts +11 −9
252 252
	);
253 253
	const publishDate = new Date(post.frontmatter.publishDate);
254 254
255 -
	// Determine textContent: use configured field from frontmatter, or fallback to markdown body
256 -
	let textContent: string;
255 +
	// Determine textContent (if enabled): use configured field from frontmatter, or fallback to markdown body
256 +
	let textContent: string | null = null;
257 257
	if (
258 +
		config.publishContent &&
258 259
		config.textContentField &&
259 260
		post.rawFrontmatter?.[config.textContentField]
260 261
	) {
261 262
		textContent = String(post.rawFrontmatter[config.textContentField]);
262 -
	} else {
263 +
	} else if (config.publishContent) {
263 264
		textContent = stripMarkdownForText(post.content);
264 265
	}
265 266
268 269
		title: post.frontmatter.title,
269 270
		site: config.publicationUri,
270 271
		path: postPath,
271 -
		textContent: textContent.slice(0, 10000),
272 +
		textContent: textContent?.slice(0, 10000),
272 273
		publishedAt: publishDate.toISOString(),
273 274
		canonicalUrl: `${config.siteUrl}${postPath}`,
274 275
	};
317 318
	);
318 319
	const publishDate = new Date(post.frontmatter.publishDate);
319 320
320 -
	// Determine textContent: use configured field from frontmatter, or fallback to markdown body
321 -
	let textContent: string;
321 +
	// Determine textContent (if enabled): use configured field from frontmatter, or fallback to markdown body
322 +
	let textContent: string | null = null;
322 323
	if (
324 +
		config.publishContent &&
323 325
		config.textContentField &&
324 326
		post.rawFrontmatter?.[config.textContentField]
325 327
	) {
326 328
		textContent = String(post.rawFrontmatter[config.textContentField]);
327 -
	} else {
329 +
	} else if (config.publishContent) {
328 330
		textContent = stripMarkdownForText(post.content);
329 331
	}
330 332
342 344
		title: post.frontmatter.title,
343 345
		site: config.publicationUri,
344 346
		path: postPath,
345 -
		textContent: textContent.slice(0, 10000),
347 +
		textContent: textContent?.slice(0, 10000),
346 348
		publishedAt: publishDate.toISOString(),
347 349
		canonicalUrl: `${config.siteUrl}${postPath}`,
348 350
	};
384 386
	title: string;
385 387
	site: string;
386 388
	path: string;
387 -
	textContent: string;
389 +
	textContent?: string;
388 390
	publishedAt: string;
389 391
	canonicalUrl?: string;
390 392
	description?: string;
packages/cli/src/lib/config.ts +8 −1
85 85
	stripDatePrefix?: boolean;
86 86
	pathTemplate?: string;
87 87
	textContentField?: string;
88 +
	publishContent?: boolean;
88 89
	bluesky?: BlueskyConfig;
89 90
}): string {
90 91
	const config: Record<string, unknown> = {
91 -
		$schema: 'https://tangled.org/stevedylan.dev/sequoia/raw/main/sequoia.schema.json',
92 +
		$schema:
93 +
			"https://tangled.org/stevedylan.dev/sequoia/raw/main/sequoia.schema.json",
92 94
		siteUrl: options.siteUrl,
93 95
		contentDir: options.contentDir,
94 96
	};
138 140
	if (options.textContentField) {
139 141
		config.textContentField = options.textContentField;
140 142
	}
143 +
144 +
	if (options.publishContent) {
145 +
		config.publishContent = options.publishContent;
146 +
	}
147 +
141 148
	if (options.bluesky) {
142 149
		config.bluesky = options.bluesky;
143 150
	}
packages/cli/src/lib/types.ts +1 −0
41 41
	stripDatePrefix?: boolean; // Remove YYYY-MM-DD- prefix from filenames (Jekyll-style, default: false)
42 42
	pathTemplate?: string; // URL path template with tokens like {year}/{month}/{day}/{slug} (overrides pathPrefix + slug)
43 43
	textContentField?: string; // Frontmatter field to use for textContent instead of markdown body
44 +
	publishContent?: boolean; // Whether or not to publish the documents content on the standard.site document (default: true)
44 45
	bluesky?: BlueskyConfig; // Optional Bluesky posting configuration
45 46
	ui?: UIConfig; // Optional UI components configuration
46 47
}
sequoia.schema.json +5 −0
116 116
			"type": "string",
117 117
			"description": "Frontmatter field to use for textContent instead of markdown body"
118 118
		},
119 +
		"publishContent": {
120 +
			"type": "boolean",
121 +
			"description": "Whether or not to publish the documents content on the standard.site document",
122 +
			"default": true
123 +
		},
119 124
		"bluesky": {
120 125
			"type": "object",
121 126
			"additionalProperties": false,