diff --git a/skills/website-creator/scripts/create_astro_website.py b/skills/website-creator/scripts/create_astro_website.py index 8c008fe..3524fe8 100644 --- a/skills/website-creator/scripts/create_astro_website.py +++ b/skills/website-creator/scripts/create_astro_website.py @@ -39,57 +39,62 @@ from urllib.parse import urlparse # INTERACTIVE SETUP FUNCTIONS # ============================================================================ + def ask_analytics_setup(): """ Interactive analytics setup workflow - + Returns: dict: Analytics configuration """ print("\n" + "=" * 60) print("š ANALYTICS SETUP") print("=" * 60) - + config = { - 'search_console': None, - 'analytics_type': None, # 'umami' or 'ga4' - 'umami_auto_create': False, - 'umami_website_id': None, - 'ga4_property_id': None, - 'ga4_credentials_path': None, - 'ga4_existing': False + "search_console": None, + "analytics_type": None, # 'umami' or 'ga4' + "umami_auto_create": False, + "umami_website_id": None, + "ga4_property_id": None, + "ga4_credentials_path": None, + "ga4_existing": False, } - + # Step 1: Google Search Console (for all websites) print("\n1ļøā£ Google Search Console Setup") print(" GSC is recommended for all websites for SEO monitoring.") - - gsc_choice = input("\n Do you want to setup Google Search Console? (y/n): ").strip().lower() - - if gsc_choice == 'y': + + gsc_choice = ( + input("\n Do you want to setup Google Search Console? (y/n): ") + .strip() + .lower() + ) + + if gsc_choice == "y": print("\n GSC Setup Options:") print(" 1. I'll add it manually later (skip for now)") print(" 2. I have service account credentials file") - + gsc_method = input("\n Choose option (1-2): ").strip() - - if gsc_method == '2': + + if gsc_method == "2": gsc_path = input(" Enter path to GSC credentials file: ").strip() if os.path.exists(gsc_path): - config['search_console'] = { - 'credentials_path': gsc_path, - 'setup_later': False + config["search_console"] = { + "credentials_path": gsc_path, + "setup_later": False, } print(" ā GSC credentials loaded") else: print(" ā File not found, will setup later") - config['search_console'] = {'setup_later': True} + config["search_console"] = {"setup_later": True} else: - config['search_console'] = {'setup_later': True} + config["search_console"] = {"setup_later": True} print(" ā Will setup later") else: print(" āļø Skipping GSC setup") - + # Step 2: Choose Analytics Type (Umami OR GA4) print("\n2ļøā£ Analytics Platform") print(" Choose ONE analytics platform:") @@ -101,72 +106,84 @@ def ask_analytics_setup(): print(" - Full-featured analytics") print(" - Requires Google account") print(" - Good for existing GA4 users") - + analytics_choice = input("\n Choose analytics (1-2): ").strip() - - if analytics_choice == '1': + + if analytics_choice == "1": # Umami setup - config['analytics_type'] = 'umami' + config["analytics_type"] = "umami" print("\n š Umami Analytics Setup") - + # Check if Umami credentials are configured from dotenv import load_dotenv - load_dotenv(os.path.join(os.path.dirname(__file__), '../../../.env')) - - umami_url = os.getenv('UMAMI_URL', '') - umami_username = os.getenv('UMAMI_USERNAME', '') - umami_password = os.getenv('UMAMI_PASSWORD', '') - + + load_dotenv(os.path.join(os.path.dirname(__file__), "../../../.env")) + + umami_url = os.getenv("UMAMI_URL", "") + umami_username = os.getenv("UMAMI_USERNAME", "") + umami_password = os.getenv("UMAMI_PASSWORD", "") + if umami_url and umami_username and umami_password: print(" ā Umami credentials found in .env") print(" ā Will auto-create Umami website for this project") - config['umami_auto_create'] = True + config["umami_auto_create"] = True else: print(" ā Umami credentials not configured in .env") print(" āļø Skipping Umami setup (can add manually later)") - - elif analytics_choice == '2': + + elif analytics_choice == "2": # GA4 setup - config['analytics_type'] = 'ga4' + config["analytics_type"] = "ga4" print("\n š Google Analytics 4 Setup") print(" 1. Create new GA4 property (auto-setup)") print(" 2. Use existing GA4 property (manual setup)") - + ga4_choice = input("\n Choose option (1-2): ").strip() - - if ga4_choice == '1': + + if ga4_choice == "1": print("\n ā Auto-creating GA4 properties requires API setup.") print(" āļø Will provide instructions for manual setup") - config['ga4_existing'] = False + config["ga4_existing"] = False else: print("\n Please provide your existing GA4 details:") - + # Check unified .env for GA4 credentials from dotenv import load_dotenv - load_dotenv(os.path.join(os.path.dirname(__file__), '../../../.env')) - - ga4_property_id = os.getenv('GA4_PROPERTY_ID', '') - ga4_credentials_path = os.getenv('GA4_CREDENTIALS_PATH', '') - + + load_dotenv(os.path.join(os.path.dirname(__file__), "../../../.env")) + + ga4_property_id = os.getenv("GA4_PROPERTY_ID", "") + ga4_credentials_path = os.getenv("GA4_CREDENTIALS_PATH", "") + if ga4_property_id: print(f" Found GA4 Property ID in .env: {ga4_property_id[:20]}...") - use_global = input(" Use this for this project? (y/n): ").strip().lower() - - if use_global == 'y': - config['ga4_property_id'] = ga4_property_id - config['ga4_credentials_path'] = ga4_credentials_path + use_global = ( + input(" Use this for this project? (y/n): ").strip().lower() + ) + + if use_global == "y": + config["ga4_property_id"] = ga4_property_id + config["ga4_credentials_path"] = ga4_credentials_path print(" ā Using global GA4 credentials") else: - config['ga4_property_id'] = input(" Enter GA4 Property ID: ").strip() - config['ga4_credentials_path'] = input(" Enter GA4 credentials file path: ").strip() + config["ga4_property_id"] = input( + " Enter GA4 Property ID: " + ).strip() + config["ga4_credentials_path"] = input( + " Enter GA4 credentials file path: " + ).strip() else: - config['ga4_property_id'] = input(" Enter GA4 Property ID (G-XXXXXXXXXX): ").strip() - config['ga4_credentials_path'] = input(" Enter GA4 credentials file path: ").strip() - - config['ga4_existing'] = True + config["ga4_property_id"] = input( + " Enter GA4 Property ID (G-XXXXXXXXXX): " + ).strip() + config["ga4_credentials_path"] = input( + " Enter GA4 credentials file path: " + ).strip() + + config["ga4_existing"] = True else: print(" āļø Skipping analytics setup") - + return config @@ -237,108 +254,128 @@ PACKAGE_JSON_TEMPLATE = """{{ # MAIN FUNCTION # ============================================================================ + def main(): """Main entry point.""" - parser = argparse.ArgumentParser(description='Create PDPA-compliant Astro website') - parser.add_argument('--name', required=True, help='Website name') - parser.add_argument('--type', default='corporate', - choices=['corporate', 'portfolio', 'landing', 'blog', 'ecommerce'], - help='Website type') - parser.add_argument('--languages', default='th,en', - help='Languages (comma-separated): th, en') - parser.add_argument('--primary-color', default='#2563eb', - help='Primary color (hex)') - parser.add_argument('--secondary-color', default='#1e40af', - help='Secondary color (hex)') - parser.add_argument('--features', default='blog,contact', - help='Features (comma-separated): blog, products, contact, portfolio') - parser.add_argument('--umami-id', default='', - help='Umami Website ID') - parser.add_argument('--umami-domain', default='analytics.example.com', - help='Umami domain') - parser.add_argument('--output', '-o', default='.', - help='Output directory') - parser.add_argument('--no-interactive', action='store_true', - help='Skip interactive setup (use defaults)') - + parser = argparse.ArgumentParser(description="Create PDPA-compliant Astro website") + parser.add_argument("--name", required=True, help="Website name") + parser.add_argument( + "--type", + default="corporate", + choices=["corporate", "portfolio", "landing", "blog", "ecommerce"], + help="Website type", + ) + parser.add_argument( + "--languages", default="th,en", help="Languages (comma-separated): th, en" + ) + parser.add_argument( + "--primary-color", default="#2563eb", help="Primary color (hex)" + ) + parser.add_argument( + "--secondary-color", default="#1e40af", help="Secondary color (hex)" + ) + parser.add_argument( + "--features", + default="blog,contact", + help="Features (comma-separated): blog, products, contact, portfolio", + ) + parser.add_argument("--umami-id", default="", help="Umami Website ID") + parser.add_argument( + "--umami-domain", default="analytics.example.com", help="Umami domain" + ) + parser.add_argument("--output", "-o", default=".", help="Output directory") + parser.add_argument( + "--no-interactive", + action="store_true", + help="Skip interactive setup (use defaults)", + ) + args = parser.parse_args() - + # Auto-generate admin password from project folder name - args.admin_password = Path(args.output).name.replace(' ', '').lower() - + args.admin_password = Path(args.output).name.replace(" ", "").lower() + # Load unified credentials from dotenv import load_dotenv - load_dotenv(os.path.join(os.path.dirname(__file__), '../../../.env')) - + + load_dotenv(os.path.join(os.path.dirname(__file__), "../../../.env")) + # Get Umami credentials for auto-setup - args.umami_url = os.getenv('UMAMI_URL', '') - args.umami_username = os.getenv('UMAMI_USERNAME', '') - args.umami_password = os.getenv('UMAMI_PASSWORD', '') - args.auto_setup_umami = bool(args.umami_url and args.umami_username and args.umami_password) - - languages = [lang.strip() for lang in args.languages.split(',')] - default_locale = 'en' if 'en' in languages else languages[0] - - features = [f.strip() for f in args.features.split(',')] - + args.umami_url = os.getenv("UMAMI_URL", "") + args.umami_username = os.getenv("UMAMI_USERNAME", "") + args.umami_password = os.getenv("UMAMI_PASSWORD", "") + args.auto_setup_umami = bool( + args.umami_url and args.umami_username and args.umami_password + ) + + languages = [lang.strip() for lang in args.languages.split(",")] + default_locale = "en" if "en" in languages else languages[0] + + features = [f.strip() for f in args.features.split(",")] + print(f"Creating website: {args.name}") print(f"Type: {args.type}") print(f"Languages: {languages}") print(f"Features: {features}") print(f"Output: {args.output}") - + # Interactive analytics setup (if not in no-interactive mode) analytics_config = None if not args.no_interactive: analytics_config = ask_analytics_setup() - + # Create project structure create_project(args, languages, default_locale, features) - + # Save analytics configuration to project if analytics_config: save_analytics_config(args.output, analytics_config) - + # Auto-setup Umami if credentials provided umami_website_id = args.umami_id - if args.auto_setup_umami and (not analytics_config or analytics_config.get('analytics_type') == 'umami'): + if args.auto_setup_umami and ( + not analytics_config or analytics_config.get("analytics_type") == "umami" + ): print("\nš Setting up Umami Analytics...") try: from umami_integration import setup_umami_for_website - website_domain = args.name.lower().replace(' ', '-') + '.moreminimore.com' + + website_domain = args.name.lower().replace(" ", "-") + ".moreminimore.com" success, result = setup_umami_for_website( args.umami_url, args.umami_username, args.umami_password, args.name, website_domain, - args.output + args.output, ) if success: - umami_website_id = result['website_id'] + umami_website_id = result["website_id"] print(f" ā Umami website created: {umami_website_id}") else: - print(f" ā Umami setup skipped: {result.get('error', 'Unknown error')}") + print( + f" ā Umami setup skipped: {result.get('error', 'Unknown error')}" + ) except Exception as e: print(f" ā Umami setup failed: {e}") print(" Continuing without Umami...") - + print(f"\nā Website created successfully at: {args.output}") - + # Update .env with Umami ID if auto-setup - env_file = os.path.join(args.output, '.env') + env_file = os.path.join(args.output, ".env") if os.path.exists(env_file) and umami_website_id: - with open(env_file, 'a', encoding='utf-8') as f: - f.write(f'\n# Umami Analytics (auto-configured)\n') - f.write(f'UMAMI_WEBSITE_ID={umami_website_id}\n') + with open(env_file, "a", encoding="utf-8") as f: + f.write(f"\n# Umami Analytics (auto-configured)\n") + f.write(f"UMAMI_WEBSITE_ID={umami_website_id}\n") print(f" ā Umami ID added to .env") - + print("\nNext steps:") print(f" 1. cd {args.output}") print(" 2. npm install") print(" 3. Update .env with your credentials") print(" 4. npm run dev") - + # Always ask to sync (skip if no-interactive mode) print("") print("=" * 60) @@ -347,39 +384,45 @@ def main(): print("") print("Preview at: http://localhost:4321") print("") - + # Ask if they want to sync to Gitea/Easypanel if args.no_interactive: print("ā Done! Website is ready at:", args.output) print("To sync later, run the sync command manually.") return - - sync_choice = input("Do you want to sync to Gitea and deploy to Easypanel? (y/n): ").strip().lower() - - if sync_choice != 'y': + + sync_choice = ( + input("Do you want to sync to Gitea and deploy to Easypanel? (y/n): ") + .strip() + .lower() + ) + + if sync_choice != "y": print("") print("ā Done! Website is ready at:", args.output) - print("To sync later, run this script again or use gitea-sync/easypanel-deploy skills.") + print( + "To sync later, run this script again or use gitea-sync/easypanel-deploy skills." + ) return - + print("") print("Proceeding with sync and deployment...") print("") - + # Step 1: Sync to Gitea print("š¦ Step 1/3: Syncing to Gitea...") git_url = sync_to_gitea(args.output, args.name) - + # Step 2: Deploy to Easypanel print("") print("š Step 2/3: Deploying to Easypanel...") deployment_url = deploy_to_easypanel(args.output, args.name, git_url) - + # Step 3: Verify and monitor print("") print("š Step 3/3: Monitoring deployment...") monitor_deployment(args.name) - + # Final output print("") print("=" * 60) @@ -399,32 +442,40 @@ def main(): def save_analytics_config(output_path: str, config: dict): """Save analytics configuration to project context""" - context_dir = os.path.join(output_path, 'context') + context_dir = os.path.join(output_path, "context") os.makedirs(context_dir, exist_ok=True) - + # Save data-services.json data_services = { - 'ga4': { - 'enabled': config.get('analytics_type') == 'ga4', - 'property_id': config.get('ga4_property_id', ''), - 'credentials_path': config.get('ga4_credentials_path', '') - } if config.get('analytics_type') == 'ga4' else {'enabled': False}, - 'gsc': { - 'enabled': config.get('search_console') is not None, - 'site_url': '', - 'credentials_path': config.get('search_console', {}).get('credentials_path', '') + "ga4": { + "enabled": config.get("analytics_type") == "ga4", + "property_id": config.get("ga4_property_id", ""), + "credentials_path": config.get("ga4_credentials_path", ""), + } + if config.get("analytics_type") == "ga4" + else {"enabled": False}, + "gsc": { + "enabled": config.get("search_console") is not None, + "site_url": "", + "credentials_path": config.get("search_console", {}).get( + "credentials_path", "" + ), }, - 'umami': { - 'enabled': config.get('analytics_type') == 'umami', - 'api_url': os.getenv('UMAMI_URL', ''), - 'website_id': config.get('umami_website_id', '') - } if config.get('analytics_type') == 'umami' else {'enabled': False}, - 'dataforseo': {'enabled': False} + "umami": { + "enabled": config.get("analytics_type") == "umami", + "api_url": os.getenv("UMAMI_URL", ""), + "website_id": config.get("umami_website_id", ""), + } + if config.get("analytics_type") == "umami" + else {"enabled": False}, + "dataforseo": {"enabled": False}, } - - with open(os.path.join(context_dir, 'data-services.json'), 'w', encoding='utf-8') as f: + + with open( + os.path.join(context_dir, "data-services.json"), "w", encoding="utf-8" + ) as f: json.dump(data_services, f, indent=2) - + print(f" ā Analytics config saved to context/data-services.json") @@ -432,87 +483,109 @@ def save_analytics_config(output_path: str, config: dict): # PROJECT CREATION FUNCTIONS # ============================================================================ + def create_project(args, languages, default_locale, features): """Create the Astro project structure with templates.""" output_path = Path(args.output) - project_name = args.name.lower().replace(' ', '-') + project_name = args.name.lower().replace(" ", "-") site_url = f"https://{project_name}.moreminimore.com" - + # Get template directory script_dir = Path(__file__).parent - template_dir = script_dir / 'templates' - + template_dir = script_dir / "templates" + print("\nš Creating project structure...") - + # Create directories dirs = [ - output_path / 'public' / 'images', - output_path / 'src' / 'components' / 'common', - output_path / 'src' / 'components' / 'consent', - output_path / 'src' / 'components' / 'ui', - output_path / 'src' / 'layouts', - output_path / 'src' / 'pages', - output_path / 'src' / 'pages' / default_locale, - output_path / 'src' / 'styles', - output_path / 'src' / 'content' / 'blog', - output_path / 'src' / 'lib', - output_path / 'db', + output_path / "public" / "images", + output_path / "public" / "images" / "icons", + output_path / "src" / "components" / "common", + output_path / "src" / "components" / "consent", + output_path / "src" / "components" / "ui", + output_path / "src" / "layouts", + output_path / "src" / "pages", + output_path / "src" / "pages" / default_locale, + output_path / "src" / "styles", + output_path / "src" / "content" / "blog", + output_path / "src" / "lib", + output_path / "db", ] - + for d in dirs: d.mkdir(parents=True, exist_ok=True) - + print(" ā Directory structure created") - + # Copy templates if they exist if template_dir.exists(): print(" š¦ Copying templates with IDs...") - + # Copy layouts - layout_src = template_dir / 'layouts' / 'BaseLayout.astro' + layout_src = template_dir / "layouts" / "BaseLayout.astro" if layout_src.exists(): - content = layout_src.read_text(encoding='utf-8') - content = content.replace("const siteName = 'Website Name'", f"const siteName = '{args.name}'") - content = content.replace("const siteUrl = 'https://example.com'", f"const siteUrl = '{site_url}'") - (output_path / 'src' / 'layouts' / 'BaseLayout.astro').write_text(content, encoding='utf-8') - + content = layout_src.read_text(encoding="utf-8") + content = content.replace( + "const siteName = 'Website Name'", f"const siteName = '{args.name}'" + ) + content = content.replace( + "const siteUrl = 'https://example.com'", f"const siteUrl = '{site_url}'" + ) + (output_path / "src" / "layouts" / "BaseLayout.astro").write_text( + content, encoding="utf-8" + ) + # Copy Header - header_src = template_dir / 'components' / 'common' / 'Header.astro' + header_src = template_dir / "components" / "common" / "Header.astro" if header_src.exists(): - shutil.copy(header_src, output_path / 'src' / 'components' / 'common' / 'Header.astro') - + shutil.copy( + header_src, + output_path / "src" / "components" / "common" / "Header.astro", + ) + # Copy Footer - footer_src = template_dir / 'components' / 'common' / 'Footer.astro' + footer_src = template_dir / "components" / "common" / "Footer.astro" if footer_src.exists(): - shutil.copy(footer_src, output_path / 'src' / 'components' / 'common' / 'Footer.astro') - + shutil.copy( + footer_src, + output_path / "src" / "components" / "common" / "Footer.astro", + ) + # Copy page templates - page_src = template_dir / 'pages' / 'index.astro' + page_src = template_dir / "pages" / "index.astro" if page_src.exists(): - shutil.copy(page_src, output_path / 'src' / 'pages' / default_locale / 'index.astro') - + shutil.copy( + page_src, output_path / "src" / "pages" / default_locale / "index.astro" + ) + # Copy styles - style_src = template_dir / 'styles' / 'global.css' + style_src = template_dir / "styles" / "global.css" if style_src.exists(): - shutil.copy(style_src, output_path / 'src' / 'styles' / 'global.css') - + shutil.copy(style_src, output_path / "src" / "styles" / "global.css") + + # Copy LINE icon + line_icon_src = template_dir / "icons" / "line.svg" + if line_icon_src.exists(): + icons_dir = output_path / "public" / "images" / "icons" + icons_dir.mkdir(parents=True, exist_ok=True) + shutil.copy(line_icon_src, icons_dir / "line.svg") + print(" ā LINE icon copied") + print(" ā Templates copied") - + # Create astro.config.mjs - locales_str = ', '.join([f"'{lang}'" for lang in languages]) + locales_str = ", ".join([f"'{lang}'" for lang in languages]) astro_config = ASTRO_CONFIG_TEMPLATE.format( - site_url=site_url, - locales=locales_str, - default_locale=default_locale + site_url=site_url, locales=locales_str, default_locale=default_locale ) - (output_path / 'astro.config.mjs').write_text(astro_config, encoding='utf-8') + (output_path / "astro.config.mjs").write_text(astro_config, encoding="utf-8") print(" ā astro.config.mjs created") - + # Create package.json package_json = PACKAGE_JSON_TEMPLATE.format(name=project_name) - (output_path / 'package.json').write_text(package_json, encoding='utf-8') + (output_path / "package.json").write_text(package_json, encoding="utf-8") print(" ā package.json created") - + # Create tsconfig.json tsconfig = """{ "extends": "astro/tsconfigs/strict", @@ -524,8 +597,8 @@ def create_project(args, languages, default_locale, features): } } """ - (output_path / 'tsconfig.json').write_text(tsconfig, encoding='utf-8') - + (output_path / "tsconfig.json").write_text(tsconfig, encoding="utf-8") + # Create env file env_content = f"""# Website Configuration SITE_NAME={args.name} @@ -535,11 +608,11 @@ SITE_URL={site_url} # UMAMI_WEBSITE_ID= # UMAMI_URL= """ - (output_path / '.env').write_text(env_content, encoding='utf-8') + (output_path / ".env").write_text(env_content, encoding="utf-8") print(" ā Configuration files created") - + # Create basic index page if no template - if not (output_path / 'src' / 'pages' / default_locale / 'index.astro').exists(): + if not (output_path / "src" / "pages" / default_locale / "index.astro").exists(): index_content = f"""--- import BaseLayout from '../layouts/BaseLayout.astro'; import Header from '../components/common/Header.astro'; @@ -557,10 +630,12 @@ import Footer from '../components/common/Footer.astro'; """ - (output_path / 'src' / 'pages' / default_locale / 'index.astro').write_text(index_content, encoding='utf-8') - + (output_path / "src" / "pages" / default_locale / "index.astro").write_text( + index_content, encoding="utf-8" + ) + print(" ā Basic pages created") - + # Create Dockerfile dockerfile = f"""FROM node:20-slim @@ -580,9 +655,9 @@ RUN npm run build EXPOSE 80 CMD ["npm", "run", "preview"] """ - (output_path / 'Dockerfile').write_text(dockerfile, encoding='utf-8') + (output_path / "Dockerfile").write_text(dockerfile, encoding="utf-8") print(" ā Dockerfile created") - + # Create .gitignore gitignore = """# Dependencies node_modules/ @@ -605,9 +680,9 @@ dist/ .DS_Store Thumbs.db """ - (output_path / '.gitignore').write_text(gitignore, encoding='utf-8') + (output_path / ".gitignore").write_text(gitignore, encoding="utf-8") print(" ā .gitignore created") - + return output_path @@ -615,18 +690,20 @@ def sync_to_gitea(output_path: str, repo_name: str) -> str: """Sync project to Gitea repository.""" try: # Import gitea sync functionality - sys.path.insert(0, str(Path(__file__).parent.parent / 'gitea-sync' / 'scripts')) + sys.path.insert(0, str(Path(__file__).parent.parent / "gitea-sync" / "scripts")) from sync import sync_repo - + # Use the gitea-sync script result = sync_repo( repo_name=repo_name, repo_path=output_path, description=f"Website: {repo_name}", - auto_push=True + auto_push=True, ) - if result.get('success'): - return result.get('url', f"https://git.moreminimore.com/user/{repo_name}.git") + if result.get("success"): + return result.get( + "url", f"https://git.moreminimore.com/user/{repo_name}.git" + ) else: print(f" ā Gitea sync failed: {result.get('error')}") return f"https://git.moreminimore.com/user/{repo_name}.git" @@ -641,44 +718,46 @@ def deploy_to_easypanel(output_path: str, project_name: str, git_url: str) -> st """Deploy project to Easypanel.""" try: # Import easypanel deploy functionality - sys.path.insert(0, str(Path(__file__).parent.parent / 'easypanel-deploy' / 'scripts')) + sys.path.insert( + 0, str(Path(__file__).parent.parent / "easypanel-deploy" / "scripts") + ) from deploy import ( get_session_token, create_service, update_git_source, update_build_type, deploy_service, - load_env + load_env, ) - + # Load credentials env = load_env() - username = env.get('EASYPANEL_USERNAME', '') - password = env.get('EASYPANEL_PASSWORD', '') - + username = env.get("EASYPANEL_USERNAME", "") + password = env.get("EASYPANEL_PASSWORD", "") + if not username or not password: print(" ā Easypanel credentials not found") print(" Skipping deployment - you can deploy manually later") return f"https://{project_name}.moreminimore.com" - + # Get session token token = get_session_token(username, password) if not token: print(" ā Failed to get Easypanel session") return f"https://{project_name}.moreminimore.com" - + # Create service - create_service(project_name, 'web', token) - + create_service(project_name, "web", token) + # Update git source - update_git_source(project_name, 'web', git_url, 'main', token) - + update_git_source(project_name, "web", git_url, "main", token) + # Set build type to dockerfile - update_build_type(project_name, 'web', token, 'dockerfile') - + update_build_type(project_name, "web", token, "dockerfile") + # Deploy - deploy_service(project_name, 'web', token) - + deploy_service(project_name, "web", token) + return f"https://{project_name}.moreminimore.com" except Exception as e: print(f" ā Easypanel deployment error: {e}") @@ -693,5 +772,5 @@ def monitor_deployment(project_name: str): print(" Check status at: https://panelwebsite.moreminimore.com") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/skills/website-creator/scripts/templates/components/common/Footer.astro b/skills/website-creator/scripts/templates/components/common/Footer.astro index c228651..6d26bd6 100644 --- a/skills/website-creator/scripts/templates/components/common/Footer.astro +++ b/skills/website-creator/scripts/templates/components/common/Footer.astro @@ -22,9 +22,9 @@ const legalLinks = [ ]; const socialLinks = [ - { name: 'Facebook', href: 'https://facebook.com', icon: 'facebook' }, - { name: 'Line', href: 'https://line.me', icon: 'line' }, - { name: 'YouTube', href: 'https://youtube.com', icon: 'youtube' }, + { name: 'Facebook', href: 'https://facebook.com', icon: 'facebook', svg: '' }, + { name: 'Line', href: 'https://line.me', icon: 'line', svg: 'line' }, + { name: 'YouTube', href: 'https://youtube.com', icon: 'youtube', svg: '' }, ]; --- @@ -45,9 +45,13 @@ const socialLinks = [