UNPKG

cfn-forge

Version:

CloudFormation deployment automation tool with git-based workflows

360 lines (317 loc) 10.5 kB
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."