144 lines
7.4 KiB
JavaScript
144 lines
7.4 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const outputDir = path.join(__dirname, '..', 'seed');
|
|
const outputFile = path.join(outputDir, 'thred-inspired-sample-content.ghost.json');
|
|
|
|
const tags = [
|
|
{id: 'tag-books', name: 'Books', slug: 'books'},
|
|
{id: 'tag-business', name: 'Business', slug: 'business'},
|
|
{id: 'tag-tech', name: 'Tech', slug: 'tech'},
|
|
{id: 'tag-science', name: 'Science', slug: 'science'},
|
|
{id: 'tag-design', name: 'Design', slug: 'design'},
|
|
{id: 'tag-music', name: 'Music', slug: 'music'},
|
|
{id: 'tag-health', name: 'Health', slug: 'health'},
|
|
{id: 'tag-gaming', name: 'Gaming', slug: 'gaming'},
|
|
{id: 'tag-travel', name: 'Travel', slug: 'travel'},
|
|
{id: 'tag-diy', name: 'DIY', slug: 'diy'}
|
|
];
|
|
|
|
const postBlueprints = [
|
|
['books', 'Independent bookstores worth planning a full afternoon around', 'A short guide to cozy stores, smart curation, and how to browse without rushing the experience.'],
|
|
['books', 'How to build a reading routine when your schedule is a mess', 'Simple habits for reading more consistently without turning books into another productivity task.'],
|
|
['business', 'Pricing freelance design work without undercutting your future self', 'A practical framework for deciding rates, packaging work, and handling client expectations early.'],
|
|
['business', 'What small teams should document before they scale too fast', 'The lightweight systems that reduce chaos before hiring and handoff complexity grow.'],
|
|
['tech', 'Setting up your first home server without making it too complicated', 'A beginner-friendly overview of hardware choices, storage planning, and sensible first services.'],
|
|
['tech', 'AI tools that feel genuinely useful in a daily workflow', 'A grounded look at where automation helps, where it interrupts, and how to evaluate tradeoffs.'],
|
|
['science', 'Climate reporting habits that make difficult research easier to follow', 'How to read scientific updates with context, avoid hype, and keep track of what changed.'],
|
|
['science', 'What makes a good science explainer feel trustworthy', 'Clarity, framing, and citation habits that help complex ideas stay readable without becoming shallow.'],
|
|
['design', 'Portfolio case studies that show thinking instead of decoration', 'How to structure project stories so decisions, constraints, and outcomes are easy to understand.'],
|
|
['design', 'Why some interfaces feel calm even when they are information dense', 'Spacing, hierarchy, rhythm, and restraint working together to reduce visual stress.'],
|
|
['music', 'Starter listening setups that make home music sessions more enjoyable', 'A realistic guide to headphones, speakers, and desk setups for focused everyday listening.'],
|
|
['music', 'Beginner friendly ways to organize samples before a project gets messy', 'Folder structures, naming patterns, and curation habits that save time later.'],
|
|
['health', 'Morning routines that support energy without pretending every day is perfect', 'Flexible routines for sleep, movement, hydration, and focus that can survive real schedules.'],
|
|
['health', 'Meal prep ideas for people who get bored of repeating the same lunch', 'Modular ingredients and simple flavor changes that keep weekday meals easier to sustain.'],
|
|
['gaming', 'Games that are easy to recommend when friends like different genres', 'A list of accessible picks that still feel distinct in pacing, tone, and challenge.'],
|
|
['gaming', 'What actually matters most in a first gaming PC build', 'The parts worth prioritizing, where to save money, and how to avoid lopsided builds.'],
|
|
['travel', 'A slower approach to city travel for people who hate checklist tourism', 'How to shape a trip around neighborhoods, cafés, bookstores, and repeated visits instead of rushing.'],
|
|
['travel', 'Packing for a week with one bag without feeling underprepared', 'A calm, repeatable packing system focused on layering, daily use, and fewer just-in-case items.'],
|
|
['diy', 'Home workshop basics for makers who only have a small corner to work in', 'The compact tools and storage habits that make limited spaces feel surprisingly capable.'],
|
|
['diy', 'Simple repair projects that build confidence before bigger DIY upgrades', 'Low-risk weekend fixes that teach useful fundamentals without requiring specialist equipment.']
|
|
];
|
|
|
|
const featureImages = {
|
|
books: 'https://images.unsplash.com/photo-1521587760476-6c12a4b040da?auto=format&fit=crop&w=1200&q=80',
|
|
business: 'https://images.unsplash.com/photo-1552664730-d307ca884978?auto=format&fit=crop&w=1200&q=80',
|
|
tech: 'https://images.unsplash.com/photo-1518770660439-4636190af475?auto=format&fit=crop&w=1200&q=80',
|
|
science: 'https://images.unsplash.com/photo-1532187863486-abf9dbad1b69?auto=format&fit=crop&w=1200&q=80',
|
|
design: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?auto=format&fit=crop&w=1200&q=80',
|
|
music: 'https://images.unsplash.com/photo-1511379938547-c1f69419868d?auto=format&fit=crop&w=1200&q=80',
|
|
health: 'https://images.unsplash.com/photo-1517836357463-d25dfeac3438?auto=format&fit=crop&w=1200&q=80',
|
|
gaming: 'https://images.unsplash.com/photo-1542751371-adc38448a05e?auto=format&fit=crop&w=1200&q=80',
|
|
travel: 'https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?auto=format&fit=crop&w=1200&q=80',
|
|
diy: 'https://images.unsplash.com/photo-1504148455328-c376907d081c?auto=format&fit=crop&w=1200&q=80'
|
|
};
|
|
|
|
function toMobiledoc(paragraphs) {
|
|
return JSON.stringify({
|
|
version: '0.3.1',
|
|
atoms: [],
|
|
cards: [],
|
|
markups: [],
|
|
sections: paragraphs.map((text) => [1, 'p', [[0, [], 0, text]]])
|
|
});
|
|
}
|
|
|
|
function toSlug(text) {
|
|
return text
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9\s-]/g, '')
|
|
.trim()
|
|
.replace(/\s+/g, '-');
|
|
}
|
|
|
|
function dateString(offsetDays) {
|
|
const date = new Date(Date.UTC(2026, 1, 1, 3, 0, 0));
|
|
date.setUTCDate(date.getUTCDate() - offsetDays);
|
|
return date.toISOString().slice(0, 19).replace('T', ' ');
|
|
}
|
|
|
|
const posts = [];
|
|
const postsMeta = [];
|
|
const postsTags = [];
|
|
|
|
postBlueprints.forEach(([tagSlug, title, excerpt], index) => {
|
|
const postId = `post-${index + 1}`;
|
|
const tag = tags.find((item) => item.slug === tagSlug);
|
|
const body = [
|
|
excerpt,
|
|
'This sample post exists to help preview archive lists, tag pages, and reading layouts while the theme is being refined.',
|
|
'Once the structure and styling feel right, these placeholders can be replaced with real editorial content inside Ghost Admin.'
|
|
];
|
|
|
|
posts.push({
|
|
id: postId,
|
|
title,
|
|
slug: toSlug(title),
|
|
status: 'published',
|
|
visibility: 'public',
|
|
type: 'post',
|
|
featured: index % 5 === 0,
|
|
custom_excerpt: excerpt,
|
|
feature_image: featureImages[tagSlug],
|
|
mobiledoc: toMobiledoc(body),
|
|
created_at: dateString(index + 3),
|
|
updated_at: dateString(index + 2),
|
|
published_at: dateString(index + 3)
|
|
});
|
|
|
|
postsMeta.push({
|
|
post_id: postId,
|
|
feature_image_alt: `${tag.name} sample article cover image`,
|
|
feature_image_caption: `${tag.name} category sample content`
|
|
});
|
|
|
|
postsTags.push({
|
|
post_id: postId,
|
|
tag_id: tag.id
|
|
});
|
|
});
|
|
|
|
const payload = {
|
|
db: [
|
|
{
|
|
meta: {
|
|
exported_on: Date.now(),
|
|
version: '6.28.0'
|
|
},
|
|
data: {
|
|
posts,
|
|
posts_meta: postsMeta,
|
|
tags,
|
|
posts_tags: postsTags,
|
|
users: [],
|
|
posts_authors: []
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
fs.mkdirSync(outputDir, {recursive: true});
|
|
fs.writeFileSync(outputFile, JSON.stringify(payload, null, 2));
|
|
|
|
console.log(`Sample Ghost import written to ${outputFile}`);
|