#!/usr/bin/env nu # Web Builder Framework CLI # Multi-page web builder with shared assets and optimization # Framework paths let FRAMEWORK_ROOT = ($env.PWD) let FRAMEWORK_CORE = ($FRAMEWORK_ROOT | path join "framework" "core") let FRAMEWORK_OPTIMIZERS = ($FRAMEWORK_ROOT | path join "framework" "optimizers") let FRAMEWORK_TEMPLATES = ($FRAMEWORK_ROOT | path join "framework" "templates") let SHARED_ASSETS = ($FRAMEWORK_ROOT | path join "shared") let PAGES_DIR = ($FRAMEWORK_ROOT | path join "pages") let SITES_DIR = ($FRAMEWORK_ROOT | path join "sites") # Import framework modules will be done dynamically in functions # Main CLI entry point def main [command?: string = "help"] { match $command { "help" => { show_help } "page" => { print "Use: wb page . Run 'wb page help' for options." } "site" => { print "Use: wb site . Run 'wb site help' for options." } "shared" => { print "Use: wb shared . Run 'wb shared help' for options." } "init" => { print "Use: wb init " } "dev" => { print "Use: wb dev [--port N]. Shortcut for 'wb page dev --watch'" } "build-all" => { build_all_pages } "clean" => { clean_all_builds } _ => { show_help } } } # Page management commands def "main page" [ subcommand: string = "help", name?: string, --template(-t): string = "single", --dev(-d), --prod(-p), --watch(-w), --port: int = 8080 ] { match $subcommand { "create" => { if ($name | is-empty) { print "Error: Page name required" return } create_page $name $template } "build" => { if ($name | is-empty) { print "Error: Page name required" return } if $dev { build_page_dev $name } else if $prod { build_page_prod $name } else { build_page_dev $name } } "dev" => { if ($name | is-empty) { print "Error: Page name required" return } dev_page $name $port $watch } "list" => { list_pages } "help" => { show_page_help } _ => { show_page_help } } } # Site management commands def "main site" [ subcommand: string = "help", name?: string ] { match $subcommand { "create" => { if ($name | is-empty) { print "Error: Site name required" return } create_site $name } "build" => { if ($name | is-empty) { print "Error: Site name required" return } build_site $name } "list" => { list_sites } "help" => { show_site_help } _ => { show_site_help } } } # Shared asset management def "main shared" [ subcommand: string = "help", file?: string, --type(-t): string = "css" ] { match $subcommand { "add" => { if ($file | is-empty) { print "Error: File path required" return } add_shared_asset $file $type } "list" => { list_shared_assets } "help" => { show_shared_help } _ => { show_shared_help } } } # Initialize new project def "main init" [project_name: string] { print $"๐Ÿš€ Initializing Web Builder project: ($project_name)" # Create project structure mkdir $project_name cd $project_name # Copy framework cp -r $FRAMEWORK_ROOT $project_name print $"โœ… Project ($project_name) initialized successfully!" print $"๐Ÿ“ Navigate to the project: cd ($project_name)" print $"๐ŸŽฏ Create your first page: ./wb page create homepage" } # Load page configuration with asset resolution export def load_page_config [page_name: string] { let page_config_path = ($PAGES_DIR | path join $page_name "config.toml") if not ($page_config_path | path exists) { error make {msg: $"Page config not found: ($page_config_path)"} } let config = (open $page_config_path) # Return config as-is for now (asset resolution will be done in build scripts) $config } # Resolve asset paths (@shared, @page references) export def resolve_asset_path [asset_path: string] { if ($asset_path | str starts-with "@shared/") { let relative_path = ($asset_path | str replace "@shared/" "") ($SHARED_ASSETS | path join $relative_path) } else if ($asset_path | str starts-with "@page/") { let parts = ($asset_path | str replace "@page/" "" | split row "/") let page_name = ($parts | first) let asset_path = ($parts | skip 1 | str join "/") ($PAGES_DIR | path join $page_name "src" "assets" $asset_path) } else { $asset_path } } # Create new page from template def create_page [name: string, template: string] { print $"๐Ÿ“ Creating page: ($name) with template: ($template)" let page_dir = ($PAGES_DIR | path join $name) if ($page_dir | path exists) { print $"โŒ Page ($name) already exists" return } # Create page structure mkdir ($page_dir | path join "src" "assets" "css") mkdir ($page_dir | path join "src" "assets" "svg") mkdir ($page_dir | path join "dist") # Copy and customize config template let template_path = ($FRAMEWORK_TEMPLATES | path join "page.config.toml.template") let config_content = (open $template_path) let customized_config = ($config_content | str replace "{{PAGE_NAME}}" $name | str replace "{{PAGE_TITLE}}" $name | str replace "{{PAGE_TYPE}}" $template | str replace "{{PAGE_DESCRIPTION}}" $"Page created with ($template) template" ) $customized_config | save ($page_dir | path join "config.toml") # Create basic HTML file let html_content = $' ($name)

($name)

Created with Web Builder Framework

' $html_content | save ($page_dir | path join "src" "index.html") # Create basic CSS let css_content = $'/* Page-specific styles for ($name) */ .container { max-width: 1200px; margin: 0 auto; padding: 2rem; text-align: center; } body { background: #0a0a0a; color: #ffffff; min-height: 100vh; display: flex; align-items: center; justify-content: center; }' $css_content | save ($page_dir | path join "src" "assets" "css" "main.css") print $"โœ… Page ($name) created successfully!" print $"๐Ÿ“ Location: ($page_dir)" print $"๐ŸŽฏ Build it: wb page build ($name)" print $"๐Ÿ”ฅ Develop: wb page dev ($name) --watch" } # Build page in development mode def build_page_dev [page_name: string] { print $"๐Ÿ”จ Building page: ($page_name) \(development mode\)" let config = (load_page_config $page_name) let page_dir = ($PAGES_DIR | path join $page_name) cd $page_dir nu ($FRAMEWORK_CORE | path join "build.nu") --dev --verbose } # Build page in production mode def build_page_prod [page_name: string] { print $"๐Ÿญ Building page: ($page_name) \(production mode\)" let config = (load_page_config $page_name) let page_dir = ($PAGES_DIR | path join $page_name) cd $page_dir nu ($FRAMEWORK_CORE | path join "prod.nu") --analyze --compress --verbose } # Start development server for page def dev_page [page_name: string, port: int, watch: bool] { print $"๐Ÿš€ Starting development server for: ($page_name)" let page_dir = ($PAGES_DIR | path join $page_name) cd $page_dir if $watch { nu ($FRAMEWORK_CORE | path join "dev.nu") --watch --port $port } else { nu ($FRAMEWORK_CORE | path join "dev.nu") --port $port } } # List all pages def list_pages [] { print "๐Ÿ“„ Available pages:" if not ($PAGES_DIR | path exists) { print " No pages found" return } ls $PAGES_DIR | where type == dir | each { |page| let page_name = ($page.name | path basename) let config_path = ($PAGES_DIR | path join $page_name "config.toml") if ($config_path | path exists) { let config = (open $config_path) print $" ๐Ÿ“ ($page_name) - ($config.page.title) [($config.page.type)]" } else { print $" ๐Ÿ“ ($page_name) - No config found" } } } # List shared assets def list_shared_assets [] { print "๐Ÿ”— Shared assets:" if not ($SHARED_ASSETS | path exists) { print " No shared assets found" return } # List CSS assets let css_dir = ($SHARED_ASSETS | path join "css") if ($css_dir | path exists) { print " ๐Ÿ“„ CSS assets:" ls -la $css_dir | each { |item| if $item.type == "dir" { let subdir = ($item.name | path basename) print $" ๐Ÿ“ ($subdir)/" let css_files = (glob ($css_dir | path join $subdir "*.css")) $css_files | each { |file| let basename = ($file | path basename) let size = (ls $file | get size | first | into int) let size_kb = ($size / 1024 | math round -p 1) print $" ๐Ÿ“ ($basename) - ($size_kb) KB" } } else if ($item.name | str ends-with ".css") { let basename = ($item.name | path basename) let size = ($item.size | into int) let size_kb = ($size / 1024 | math round -p 1) print $" ๐Ÿ“ ($basename) - ($size_kb) KB" } } } # List SVG assets let svg_dir = ($SHARED_ASSETS | path join "svg") if ($svg_dir | path exists) { print " ๐Ÿ–ผ๏ธ SVG assets:" let svg_files = (glob ($svg_dir | path join "*.svg")) $svg_files | each { |file| let basename = ($file | path basename) let size = (ls $file | get size | first | into int) let size_kb = ($size / 1024 | math round -p 1) print $" ๐Ÿ“ ($basename) - ($size_kb) KB" } } # List JS assets let js_dir = ($SHARED_ASSETS | path join "js") if ($js_dir | path exists) { print " ๐Ÿ“œ JavaScript assets:" let js_files = (glob ($js_dir | path join "*.js")) $js_files | each { |file| let basename = ($file | path basename) let size = (ls $file | get size | first | into int) let size_kb = ($size / 1024 | math round -p 1) print $" ๐Ÿ“ ($basename) - ($size_kb) KB" } } } # Add shared asset def add_shared_asset [file_path: string, asset_type: string] { print $"๐Ÿ“ฆ Adding shared asset: ($file_path) as ($asset_type)" if not ($file_path | path exists) { print $"โŒ File not found: ($file_path)" return } # Create shared assets directory structure mkdir ($SHARED_ASSETS | path join $asset_type) # Copy file to shared assets let filename = ($file_path | path basename) let dest_path = ($SHARED_ASSETS | path join $asset_type $filename) cp $file_path $dest_path print $"โœ… Added shared asset: @shared/($asset_type)/($filename)" print $" Use in page config: \"@shared/($asset_type)/($filename)\"" } # Create multi-page site def create_site [name: string] { print $"๐ŸŒ Creating site: ($name)" let site_dir = ($SITES_DIR | path join $name) if ($site_dir | path exists) { print $"โŒ Site ($name) already exists" return } # Create site structure mkdir ($site_dir | path join "pages") mkdir ($site_dir | path join "shared") mkdir ($site_dir | path join "dist") # Create site configuration let site_config = $'[site] name = "($name)" title = "($name)" description = "Multi-page site created with Web Builder Framework" [build] output_dir = "dist" shared_assets = true [pages] # Add page references here # homepage = { path = "homepage", template = "landing" } ' $site_config | save ($site_dir | path join "site.toml") print $"โœ… Site ($name) created successfully!" print $"๐Ÿ“ Location: ($site_dir)" print $"๐ŸŽฏ Add pages to the site configuration" } # Build multi-page site def build_site [name: string] { print $"๐Ÿ—๏ธ Building site: ($name)" let site_dir = ($SITES_DIR | path join $name) let site_config_path = ($site_dir | path join "site.toml") if not ($site_config_path | path exists) { print $"โŒ Site config not found: ($site_config_path)" return } let site_config = (open $site_config_path) print $"๐Ÿ“ฆ Building all pages for site: ($site_config.site.title)" print " (Site building not fully implemented yet - build individual pages for now)" # TODO: Implement multi-page site building # This would iterate through all pages defined in site.toml # and build them into a unified site structure } # List all sites def list_sites [] { print "๐ŸŒ Available sites:" if not ($SITES_DIR | path exists) { print " No sites found" return } ls $SITES_DIR | where type == dir | each { |site| let site_name = ($site.name | path basename) let config_path = ($SITES_DIR | path join $site_name "site.toml") if ($config_path | path exists) { let config = (open $config_path) print $" ๐ŸŒ ($site_name) - ($config.site.title)" } else { print $" ๐ŸŒ ($site_name) - No config found" } } } # Help functions def show_help [] { print "๐ŸŒ Web Builder Framework" print "========================" print "" print "Commands:" print " wb page - Manage individual pages" print " wb site - Manage multi-page sites" print " wb shared - Manage shared assets" print " wb init - Initialize new project" print " wb dev [--port N] - Quick dev server (shortcut)" print " wb build-all [--prod] - Build all pages" print " wb clean [--all] - Clean build artifacts" print " wb help - Show this help" print "" print "Examples:" print " wb page create homepage" print " wb dev homepage - Quick development server" print " wb page build homepage --prod" print " wb build-all --prod - Build all pages for production" print " wb clean --all - Deep clean all artifacts" print " wb shared list" print "" print "๐Ÿ’ก For faster JS minification, install SWC:" print " npm install -g @swc/cli @swc/core" } def show_page_help [] { print "๐Ÿ“„ Page Management" print "==================" print "" print "Commands:" print " wb page create [--template ] - Create new page" print " wb page build [--dev|--prod] - Build page" print " wb page dev [--watch] [--port N] - Start dev server" print " wb page list - List all pages" print "" print "Templates: single, landing, article, poster" print "" print "Examples:" print " wb page create about --template landing" print " wb page dev homepage --watch --port 3000" } def show_site_help [] { print "๐ŸŒ Site Management" print "==================" print " wb site create - Create multi-page site" print " wb site build - Build entire site" print " wb site list - List all sites" } def show_shared_help [] { print "๐Ÿ”— Shared Assets" print "================" print " wb shared add --type - Add shared asset" print " wb shared list - List shared assets" } # Shortcut commands def "main dev" [page?: string = "homepage", --port: int = 8080] { if ($page | is-empty) { print "Error: Page name required" print "Usage: wb dev [--port N]" return } print $"๐Ÿš€ Starting development server for: ($page)" dev_page $page $port true # true for watch mode } def "main build-all" [--prod(-p)] { print "๐Ÿ—๏ธ Building all pages..." if not ($PAGES_DIR | path exists) { print "โŒ No pages directory found" return } let pages = (ls $PAGES_DIR | where type == dir | get name) if ($pages | length) == 0 { print "๐Ÿ“„ No pages found to build" return } print $"๐Ÿ“ฆ Found ($pages | length) pages to build" for page_path in $pages { let page_name = ($page_path | path basename) let config_path = ($page_path | path join "config.toml") if ($config_path | path exists) { print $"๐Ÿ”จ Building ($page_name)..." if $prod { build_page_prod $page_name } else { build_page_dev $page_name } print $"โœ… ($page_name) completed" } else { print $"โš ๏ธ Skipping ($page_name) - no config found" } } print "๐ŸŽ‰ All pages built successfully!" } def "main clean" [--all(-a)] { print "๐Ÿงน Cleaning build artifacts..." if not ($PAGES_DIR | path exists) { print "โŒ No pages directory found" return } let pages = (ls $PAGES_DIR | where type == dir | get name) mut cleaned_count = 0 for page_path in $pages { let page_name = ($page_path | path basename) let dist_dir = ($page_path | path join "dist") if ($dist_dir | path exists) { print $"๐Ÿ—‘๏ธ Cleaning ($page_name)/dist/" rm -rf $dist_dir $cleaned_count = ($cleaned_count + 1) } } if $all { # Clean additional artifacts print "๐Ÿงฝ Deep cleaning..." # Clean compressed files for page_path in $pages { let page_name = ($page_path | path basename) glob ($page_path | path join "**/*.gz") | each { |file| if ($file | path exists) { print $"๐Ÿ—‘๏ธ Removing ($file | path basename)" rm $file } } } } print $"โœ… Cleaned ($cleaned_count) pages" }