Fix demo site auto-enhancement and content persistence

- Restructure demo directory from test-sites/ to demos/ with flattened layout
- Add auto-enhancement on server startup for all sites with auto_enhance: true
- Fix inconsistent content ID generation that prevented dan-eden-portfolio content persistence
- Update server configuration to enhance from source to separate output directories
- Remove manual enhancement from justfile in favor of automatic server enhancement
- Clean up legacy test files and unused restore command
- Update build system to use CDN endpoint instead of file copying
This commit is contained in:
2025-09-17 00:07:40 +02:00
parent 1fa607c47c
commit 71561316da
73 changed files with 190 additions and 4827 deletions

View File

@@ -51,7 +51,7 @@ func runEnhance(cmd *cobra.Command, args []string) {
outputDir := viper.GetString("cli.output")
// Auto-derive site_id for demo paths or validate for production
if strings.Contains(inputDir, "/demos/") {
if strings.Contains(inputDir, "/demos/") || strings.Contains(inputDir, "./demos/") {
// Auto-derive site_id from demo path
siteID = content.DeriveOrValidateSiteID(inputDir, siteID)
} else {

View File

@@ -1,163 +0,0 @@
package cmd
import (
"fmt"
"log"
"sort"
"github.com/insertr/insertr/internal/content"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
timestamp string
latest bool
clean bool
)
var restoreCmd = &cobra.Command{
Use: "restore [site-id]",
Short: "Restore a site from backup",
Long: `Restore a registered site from a timestamped backup.
Examples:
insertr restore demo # List available backups
insertr restore demo --clean # Restore from oldest backup (cleanest)
insertr restore demo --latest # Restore from newest backup
insertr restore demo --timestamp 20250910-224704 # Restore from specific backup`,
Args: cobra.ExactArgs(1),
Run: runRestore,
}
func init() {
restoreCmd.Flags().StringVarP(&timestamp, "timestamp", "t", "", "specific backup timestamp to restore from")
restoreCmd.Flags().BoolVar(&latest, "latest", false, "restore from most recent backup")
restoreCmd.Flags().BoolVar(&clean, "clean", false, "restore from oldest backup (cleanest state)")
// Bind flags to viper
viper.BindPFlag("restore.timestamp", restoreCmd.Flags().Lookup("timestamp"))
viper.BindPFlag("restore.latest", restoreCmd.Flags().Lookup("latest"))
viper.BindPFlag("restore.clean", restoreCmd.Flags().Lookup("clean"))
}
func runRestore(cmd *cobra.Command, args []string) {
siteID := args[0]
// Initialize content client (we don't actually need it for restore, but SiteManager expects it)
contentClient := content.NewMockClient()
// Initialize site manager
siteManager := content.NewSiteManager(contentClient, "./insertr-backups", false)
// Load sites from configuration to register them
if siteConfigs := viper.Get("server.sites"); siteConfigs != nil {
if configs, ok := siteConfigs.([]interface{}); ok {
var sites []*content.SiteConfig
for _, configInterface := range configs {
if configMap, ok := configInterface.(map[string]interface{}); ok {
site := &content.SiteConfig{}
if id, ok := configMap["site_id"].(string); ok {
site.SiteID = id
}
if path, ok := configMap["path"].(string); ok {
site.Path = path
}
if domain, ok := configMap["domain"].(string); ok {
site.Domain = domain
}
if autoEnhance, ok := configMap["auto_enhance"].(bool); ok {
site.AutoEnhance = autoEnhance
}
if backupOriginals, ok := configMap["backup_originals"].(bool); ok {
site.BackupOriginals = backupOriginals
}
sites = append(sites, site)
}
}
if err := siteManager.RegisterSites(sites); err != nil {
log.Fatalf("Failed to register sites: %v", err)
}
}
}
// List available backups
backups, err := siteManager.ListBackups(siteID)
if err != nil {
log.Fatalf("Failed to list backups: %v", err)
}
if len(backups) == 0 {
fmt.Printf("❌ No backups found for site '%s'\n", siteID)
fmt.Printf("💡 Backups are created automatically during enhancement when backup_originals is enabled\n")
return
}
// Sort backups chronologically
sort.Strings(backups)
// Handle different restore modes
var targetTimestamp string
if timestamp != "" {
// Specific timestamp provided
targetTimestamp = timestamp
found := false
for _, backup := range backups {
if backup == targetTimestamp {
found = true
break
}
}
if !found {
fmt.Printf("❌ Backup timestamp '%s' not found for site '%s'\n", targetTimestamp, siteID)
fmt.Printf("📋 Available backups:\n")
for i, backup := range backups {
if i == 0 {
fmt.Printf(" %s (oldest/cleanest)\n", backup)
} else if i == len(backups)-1 {
fmt.Printf(" %s (newest)\n", backup)
} else {
fmt.Printf(" %s\n", backup)
}
}
return
}
} else if clean {
// Restore from oldest backup (cleanest)
targetTimestamp = backups[0]
fmt.Printf("🧹 Restoring from oldest backup (cleanest state): %s\n", targetTimestamp)
} else if latest {
// Restore from newest backup
targetTimestamp = backups[len(backups)-1]
fmt.Printf("🔄 Restoring from newest backup: %s\n", targetTimestamp)
} else {
// No specific option - list available backups
fmt.Printf("📋 Available backups for site '%s':\n", siteID)
for i, backup := range backups {
if i == 0 {
fmt.Printf(" %s (oldest/cleanest) ← use --clean\n", backup)
} else if i == len(backups)-1 {
fmt.Printf(" %s (newest) ← use --latest\n", backup)
} else {
fmt.Printf(" %s\n", backup)
}
}
fmt.Printf("\nUsage:\n")
fmt.Printf(" insertr restore %s --clean # restore from oldest backup\n", siteID)
fmt.Printf(" insertr restore %s --latest # restore from newest backup\n", siteID)
fmt.Printf(" insertr restore %s --timestamp %s # restore from specific backup\n", siteID, backups[0])
return
}
// Perform restore
fmt.Printf("🔄 Restoring site '%s' from backup %s...\n", siteID, targetTimestamp)
if err := siteManager.RestoreFromBackup(siteID, targetTimestamp); err != nil {
log.Fatalf("❌ Restore failed: %v", err)
}
fmt.Printf("✅ Successfully restored site '%s' from backup %s\n", siteID, targetTimestamp)
fmt.Printf("💡 Site files have been restored to their state from %s\n", targetTimestamp)
}

View File

@@ -52,7 +52,6 @@ func init() {
rootCmd.AddCommand(enhanceCmd)
rootCmd.AddCommand(serveCmd)
rootCmd.AddCommand(restoreCmd)
}
func initConfig() {

View File

@@ -73,7 +73,7 @@ func runServe(cmd *cobra.Command, args []string) {
contentClient := content.NewDatabaseClient(database)
// Initialize site manager
siteManager := content.NewSiteManager(contentClient, "./insertr-backups", devMode)
siteManager := content.NewSiteManager(contentClient, devMode)
// Load sites from configuration
if siteConfigs := viper.Get("server.sites"); siteConfigs != nil {
@@ -88,15 +88,15 @@ func runServe(cmd *cobra.Command, args []string) {
if path, ok := configMap["path"].(string); ok {
site.Path = path
}
if sourcePath, ok := configMap["source_path"].(string); ok {
site.SourcePath = sourcePath
}
if domain, ok := configMap["domain"].(string); ok {
site.Domain = domain
}
if autoEnhance, ok := configMap["auto_enhance"].(bool); ok {
site.AutoEnhance = autoEnhance
}
if backupOriginals, ok := configMap["backup_originals"].(bool); ok {
site.BackupOriginals = backupOriginals
}
if site.SiteID != "" && site.Path != "" {
sites = append(sites, site)
}
@@ -108,6 +108,14 @@ func runServe(cmd *cobra.Command, args []string) {
}
}
// Auto-enhance sites if enabled
if devMode {
log.Printf("🔄 Auto-enhancing sites in development mode...")
if err := siteManager.EnhanceAllSites(); err != nil {
log.Printf("⚠️ Some sites failed to enhance: %v", err)
}
}
// Initialize handlers
contentHandler := api.NewContentHandler(database, authService)
contentHandler.SetSiteManager(siteManager)