// pages/api/jekyll/create.js import { exec } from 'child_process'; import { promisify } from 'util'; import path from 'path'; import fs from 'fs-extra'; const execAsync = promisify(exec); export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } try { const { siteName, template = 'blog', config = {} } = req.body; if (!siteName || !/^[a-zA-Z0-9-_]+$/.test(siteName)) { return res.status(400).json({ error: 'Invalid site name. Use only alphanumeric, dash, and underscore.' }); } const sitePath = path.join('/app/projects', siteName); // Check if site already exists if (await fs.pathExists(sitePath)) { return res.status(409).json({ error: 'Site already exists' }); } // Create Jekyll site menggunakan entrypoint script console.log(`Creating Jekyll site: ${siteName}`); const { stdout, stderr } = await execAsync( `/usr/local/bin/entrypoint.sh create-site ${siteName}`, { timeout: 30000, cwd: '/app' } ); // Customize site based on template await customizeJekyllSite(sitePath, template, config); console.log('Jekyll site created:', stdout); if (stderr) console.warn('Jekyll warnings:', stderr); res.status(201).json({ success: true, message: 'Jekyll site created successfully', siteName, path: sitePath, previewUrl: `/preview/${siteName}`, output: stdout }); } catch (error) { console.error('Error creating Jekyll site:', error); res.status(500).json({ error: 'Failed to create Jekyll site', details: error.message, stderr: error.stderr || null }); } } async function customizeJekyllSite(sitePath, template, config) { try { // Update _config.yml dengan konfigurasi custom const configPath = path.join(sitePath, '_config.yml'); const defaultConfig = await fs.readFile(configPath, 'utf8'); const customConfig = `${defaultConfig} # Jekyll Studio Configuration title: ${config.title || 'My Jekyll Site'} description: ${config.description || 'Created with Jekyll Studio'} url: "" baseurl: "" # Build settings markdown: kramdown highlighter: rouge theme: minima plugins: - jekyll-feed # Exclude from processing exclude: - Gemfile - Gemfile.lock - node_modules - vendor/bundle/ - vendor/cache/ - vendor/gems/ - vendor/ruby/ `; await fs.writeFile(configPath, customConfig); // Create sample post berdasarkan template const postsDir = path.join(sitePath, '_posts'); await fs.ensureDir(postsDir); const samplePost = `--- layout: post title: "Welcome to Jekyll Studio!" date: ${new Date().toISOString().split('T')[0]} 12:00:00 +0000 categories: jekyll update --- # Welcome to Your New Jekyll Site! This site was created using **Jekyll Studio** on Hugging Face Spaces. ## Features - 🚀 Fast static site generation - 📝 Markdown support - 🎨 Customizable themes - 📱 Mobile responsive - 🔍 SEO optimized ## Getting Started Edit this post in \`_posts/\` directory or create new posts using the Jekyll Studio interface. Happy blogging! ✨ `; const postPath = path.join(postsDir, `${new Date().toISOString().split('T')[0]}-welcome-to-jekyll-studio.md`); await fs.writeFile(postPath, samplePost); console.log(`Jekyll site customized with ${template} template`); } catch (error) { console.warn('Failed to customize Jekyll site:', error.message); } }