name: static-website
description: Static website hosting with S3, CloudFront, and custom domain support
version: 1.0.0
author: CFN-Forge
cfnForgeVersion: 1.0.0

variables:
  projectName:
    prompt: "Project name"
    default: "my-static-site"
  description:
    prompt: "Project description"
    default: "A static website hosted on AWS"
  domainName:
    prompt: "Custom domain name (optional, press enter to skip)"
    default: ""
  enableSPA:
    prompt: "Enable Single Page Application routing?"
    default: "false"
    type: "boolean"

files:
  include:
    - "**/*"
  exclude:
    - "template.yaml"
    - ".git/**"
    - "node_modules/**"

structure:
  cloudformation.yaml: |
    AWSTemplateFormatVersion: '2010-09-09'
    Description: {{description}}

    Parameters:
      Environment:
        Type: String
        Default: dev
        AllowedValues: [dev, staging, prod]
        Description: Environment name

    Conditions:
      HasCustomDomain: !Not [!Equals ["{{domainName}}", ""]]
      IsSPA: !Equals ["{{enableSPA}}", "true"]

    Resources:
      # S3 Bucket for website hosting
      WebsiteBucket:
        Type: AWS::S3::Bucket
        Properties:
          BucketName: !Sub "${AWS::StackName}-website-${Environment}"
          WebsiteConfiguration:
            IndexDocument: index.html
            ErrorDocument: !If [IsSPA, "index.html", "error.html"]
          PublicReadPolicy:
            Statement:
              - Sid: PublicReadGetObject
                Effect: Allow
                Principal: "*"
                Action: s3:GetObject
                Resource: !Sub "${WebsiteBucket}/*"

      # CloudFront Distribution
      CloudFrontDistribution:
        Type: AWS::CloudFront::Distribution
        Properties:
          DistributionConfig:
            Origins:
              - DomainName: !GetAtt WebsiteBucket.RegionalDomainName
                Id: S3Origin
                S3OriginConfig:
                  OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${OriginAccessIdentity}"
            Enabled: true
            DefaultRootObject: index.html
            DefaultCacheBehavior:
              AllowedMethods: [GET, HEAD]
              Compress: true
              TargetOriginId: S3Origin
              ViewerProtocolPolicy: redirect-to-https
              CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6  # Managed caching optimized
            CustomErrorResponses:
              - !If
                - IsSPA
                - ErrorCode: 404
                  ResponseCode: 200
                  ResponsePagePath: /index.html
                - !Ref AWS::NoValue
            Aliases: !If [HasCustomDomain, [{{domainName}}], !Ref AWS::NoValue]
            ViewerCertificate: !If
              - HasCustomDomain
              - AcmCertificateArn: !Ref SSLCertificate
                SslSupportMethod: sni-only
              - CloudFrontDefaultCertificate: true
            PriceClass: PriceClass_100

      # Origin Access Identity
      OriginAccessIdentity:
        Type: AWS::CloudFront::OriginAccessIdentity
        Properties:
          OriginAccessIdentityConfig:
            Comment: !Sub "Access identity for ${AWS::StackName}"

      # SSL Certificate (only if custom domain)
      SSLCertificate:
        Type: AWS::CertificateManager::Certificate
        Condition: HasCustomDomain
        Properties:
          DomainName: {{domainName}}
          ValidationMethod: DNS

    Outputs:
      WebsiteURL:
        Description: Website URL
        Value: !If
          - HasCustomDomain
          - !Sub "https://{{domainName}}"
          - !Sub "https://${CloudFrontDistribution.DomainName}"
        Export:
          Name: !Sub "${AWS::StackName}-WebsiteURL"
      
      CloudFrontDomainName:
        Description: CloudFront Distribution Domain Name
        Value: !GetAtt CloudFrontDistribution.DomainName
        Export:
          Name: !Sub "${AWS::StackName}-CloudFrontDomain"
      
      S3BucketName:
        Description: S3 Bucket Name
        Value: !Ref WebsiteBucket
        Export:
          Name: !Sub "${AWS::StackName}-S3Bucket"

  .cfn-forge.yaml: |
    project:
      name: {{projectName}}
      description: {{description}}
      type: static-website

    environments:
      dev:
        stackName: "{{projectName}}-dev"
        template: cloudformation.yaml
        region: us-east-1
        parameters:
          Environment: dev
      
      staging:
        stackName: "{{projectName}}-staging"
        template: cloudformation.yaml
        region: us-east-1
        parameters:
          Environment: staging
      
      prod:
        stackName: "{{projectName}}-prod"
        template: cloudformation.yaml
        region: us-east-1
        parameters:
          Environment: prod

    deployment:
      packagingBucket: "{{projectName}}-deployment-artifacts"
      createBucket: true
      git:
        watchBranches: ["main", "develop"]
        deployOnPush: true

  package.json: |
    {
      "name": "{{projectName}}",
      "version": "1.0.0",
      "description": "{{description}}",
      "scripts": {
        "build": "echo 'Add your build command here'",
        "deploy": "cfn-forge deploy",
        "watch": "cfn-forge watch",
        "validate": "cfn-forge validate",
        "sync": "aws s3 sync ./dist s3://$(cfn-forge config get bucket) --delete",
        "invalidate": "aws cloudfront create-invalidation --distribution-id $(cfn-forge config get distribution) --paths '/*'"
      },
      "devDependencies": {
        "live-server": "^1.2.2"
      },
      "keywords": ["static", "website", "aws", "s3", "cloudfront"],
      "author": "{{author}}",
      "license": "MIT"
    }

  public/index.html: |
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{projectName}}</title>
        <style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
                max-width: 800px;
                margin: 0 auto;
                padding: 2rem;
                line-height: 1.6;
                color: #333;
            }
            .hero {
                text-align: center;
                padding: 3rem 0;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                border-radius: 10px;
                margin-bottom: 2rem;
            }
            .features {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                gap: 2rem;
                margin: 2rem 0;
            }
            .feature {
                padding: 1.5rem;
                border: 1px solid #ddd;
                border-radius: 8px;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div class="hero">
            <h1>Welcome to {{projectName}}</h1>
            <p>{{description}}</p>
        </div>
        
        <div class="features">
            <div class="feature">
                <h3>🚀 Fast Deployment</h3>
                <p>Deploy your site to AWS with a single command using CFN-Forge</p>
            </div>
            <div class="feature">
                <h3>⚡ Global CDN</h3>
                <p>Your site is served through CloudFront for lightning fast load times</p>
            </div>
            <div class="feature">
                <h3>🔒 HTTPS Enabled</h3>
                <p>SSL certificate automatically provisioned for secure connections</p>
            </div>
        </div>
        
        <footer style="text-align: center; margin-top: 3rem; color: #666;">
            <p>Built with ❤️ using CFN-Forge</p>
        </footer>
    </body>
    </html>

  public/error.html: |
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page Not Found - {{projectName}}</title>
        <style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
                max-width: 600px;
                margin: 0 auto;
                padding: 2rem;
                text-align: center;
                color: #333;
            }
            .error-code {
                font-size: 4rem;
                font-weight: bold;
                color: #e74c3c;
                margin-bottom: 1rem;
            }
        </style>
    </head>
    <body>
        <div class="error-code">404</div>
        <h1>Page Not Found</h1>
        <p>The page you're looking for doesn't exist.</p>
        <a href="/">← Go back home</a>
    </body>
    </html>

  README.md: |
    # {{projectName}}

    {{description}}

    ## Quick Start

    1. Build your site (if needed):
       ```bash
       npm run build
       ```

    2. Deploy to AWS:
       ```bash
       cfn-forge deploy
       ```

    3. Start local development:
       ```bash
       cfn-forge watch
       ```

    ## Project Structure

    ```
    {{projectName}}/
       public/
          index.html        # Main page
          error.html        # 404 error page
       cloudformation.yaml  # AWS infrastructure
       .cfn-forge.yaml     # CFN-Forge configuration
       package.json
    ```

    ## Features

    - ✅ S3 static website hosting
    - ✅ CloudFront CDN for global performance
    - ✅ SSL certificate (HTTPS)
    - ✅ Custom domain support
    - ✅ Single Page Application routing (optional)
    - ✅ Automatic deployment with CFN-Forge

    ## Deployment

    The site is automatically deployed using AWS CloudFormation through CFN-Forge.

    ### Environments

    - **dev**: Development environment
    - **staging**: Staging environment  
    - **prod**: Production environment

    ### Custom Domain

    If you specified a custom domain during setup, make sure to:
    1. Update your domain's DNS to point to the CloudFront distribution
    2. Verify the SSL certificate in AWS Certificate Manager

    ### Content Updates

    After deploying infrastructure, sync your content:

    ```bash
    # Sync files to S3
    npm run sync

    # Invalidate CloudFront cache
    npm run invalidate
    ```

hooks:
  postInstall:
    - type: message
      content: "Static website template created! Add your content to the 'public' directory."