Cloud infra
for humans

Architect gives you the power to configure, locally build, and globally deploy web apps to the cloud using concise, declarative statements. Built on rock solid AWS foundations, Architect makes advanced web development a breeze.

Get started

Open governance

Sponsored development

Seamless development, from local to cloud

Scaffold a fresh Architect project with a single command.

Node

> npm init @architect your-app

⚬ Bootstrapping new Architect project

| Project name .. your-app

| Creating in ... /Users/LouisK/Developer/your-app

⚬ Installing Architect...

✓ Your Architect project is ready!

Get a local, production-like environment up and running instantly.

Node

> npx arc sandbox

App ⌁ your-app

Region ⌁ us-west-2

http://localhost:3333

✓ Sandbox started in 12ms

❤︎ Local environment ready!

Deploy to identical staging and production environments in seconds.

Node

> npx arc deploy

App ⌁ your-app

Region ⌁ us-west-2

⚬ Creating new private deployment bucket

✓ Generated CloudFormation deployment

✓ Deployed & built infrastructure

✓ Success! Deployed app in 58.984 seconds

Why Architect?

Architect provides everything you need to build massively scalable Functional Web Apps on AWS with low code, clear and terse config, and zero ceremony.

Fullstack, for real

Architect not only supports cloud functions for HTTP but also web sockets, queues (FIFO), events (fan-out), and scheduled tasks backed by a world class database that boasts millisecond latency no matter how much data you store or how many people concurrently access it. All these capabilities, and more, with terse but determinstic Infra-as-Code (IaC).

The best developer experience

We prioritize speed with fast local dev, smart configurable defaults and flexible Infrastructure as Code. You can focus on business logic instead of glue code — and only pay for in-use services on-demand, while otherwise scaling to zero.

Intelligent, efficient iteration

Architect treats local development, staging, and production environments as first class concerns. Architect developers iterate fast with all of these environments and deployments only seconds away, leading to reduced latency in feedback cycles.

Infrastructure as code

Architect turns formerly complex cloud infrastructure provisioning into a build artifact, so infra and code are always aligned and deterministic. It then compiles manifest code into AWS CloudFormation and deploys it.

IaC: NP!

Infrastructure as Code (IaC) can be intimidating for even the most experienced developers. Architect's manifest file — which can be written in multiple open text formats — codifies cloud infrastructure provisioning as a minimal build artifact, turning formerly complex work into approachable, maintainable code.

See the difference for yourself by exploring the examples of Architect project manifests and the CloudFormation configurations they generate below. Or try the interactive Architect playground.

Architect manifest

4 lines of config

@appmyapp@httpget/

CloudFormation

369 lines of IaC template

{
 "AWSTemplateFormatVersion": "2010-09-09",
 "Transform": "AWS::Serverless-2016年10月31日",
 "Description": "Example: hello world",
 "Resources": {
 "Role": {
 "Type": "AWS::IAM::Role",
 "Properties": {
 "AssumeRolePolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": {
 "Service": "lambda.amazonaws.com"
 },
 "Action": "sts:AssumeRole"
 }
 ]
 },
 "Policies": [
 {
 "PolicyName": "ArcGlobalPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "logs:CreateLogGroup",
 "logs:CreateLogStream",
 "logs:PutLogEvents",
 "logs:DescribeLogStreams"
 ],
 "Resource": "arn:aws:logs:*:*:*"
 }
 ]
 }
 },
 {
 "PolicyName": "ArcStaticBucketPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:PutObjectAcl",
 "s3:DeleteObject",
 "s3:ListBucket"
 ],
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ]
 }
 ]
 }
 }
 ]
 }
 },
 "StaticBucketParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "bucket"
 }
 ]
 },
 "Value": {
 "Ref": "StaticBucket"
 }
 }
 },
 "StaticFingerprintParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "fingerprint"
 }
 ]
 },
 "Value": "false"
 }
 },
 "ParameterStorePolicy": {
 "Type": "AWS::IAM::Policy",
 "DependsOn": "Role",
 "Properties": {
 "PolicyName": "ArcParameterStorePolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*/*",
 {}
 ]
 }
 }
 ]
 },
 "Roles": [
 {
 "Ref": "Role"
 }
 ]
 }
 },
 "HTTP": {
 "Type": "AWS::Serverless::HttpApi",
 "Properties": {
 "StageName": "$default",
 "DefinitionBody": {
 "openapi": "3.0.1",
 "info": {
 "title": {
 "Ref": "AWS::StackName"
 }
 },
 "paths": {
 "/": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetIndexHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/_static/{proxy+}": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "1.0",
 "type": "http_proxy",
 "httpMethod": "GET",
 "uri": {
 "Fn::Sub": [
 "https://${bukkit}.s3.${AWS::Region}.amazonaws.com/{proxy}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 "connectionType": "INTERNET",
 "timeoutInMillis": 30000
 }
 }
 }
 }
 }
 }
 },
 "GetIndexHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-index",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "myapp",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_STATIC_SPA": false
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetIndexHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /",
 "method": "get",
 "path": "/"
 }
 },
 "StaticBucket": {
 "Type": "AWS::S3::Bucket",
 "Properties": {
 "OwnershipControls": {
 "Rules": [
 {
 "ObjectOwnership": "BucketOwnerEnforced"
 }
 ]
 },
 "WebsiteConfiguration": {
 "IndexDocument": "index.html",
 "ErrorDocument": "404.html"
 },
 "PublicAccessBlockConfiguration": {
 "BlockPublicAcls": false,
 "BlockPublicPolicy": false,
 "IgnorePublicAcls": false,
 "RestrictPublicBuckets": false
 }
 }
 },
 "StaticBucketPolicy": {
 "Type": "AWS::S3::BucketPolicy",
 "Properties": {
 "Bucket": {
 "Ref": "StaticBucket"
 },
 "PolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Action": [
 "s3:GetObject"
 ],
 "Effect": "Allow",
 "Principal": "*",
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ],
 "Sid": "PublicReadGetObject"
 }
 ]
 }
 }
 }
 },
 "Outputs": {
 "API": {
 "Description": "API Gateway (HTTP)",
 "Value": {
 "Fn::Sub": [
 "https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com",
 {
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 ]
 }
 },
 "ApiId": {
 "Description": "API ID (ApiId)",
 "Value": {
 "Ref": "HTTP"
 }
 },
 "BucketURL": {
 "Description": "Bucket URL",
 "Value": {
 "Fn::Sub": [
 "http://${bukkit}.s3-website-${AWS::Region}.amazonaws.com",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 }
 }
}

Architect manifest

12 lines of config

@apparc-codes@awsregionus-west-2profileopenjsf@staticfingerprinttrue@httpget/docs/:lang/*get/api/packageany/*get/landing

CloudFormation

588 lines of IaC template

{
 "AWSTemplateFormatVersion": "2010-09-09",
 "Transform": "AWS::Serverless-2016年10月31日",
 "Description": "Example: arc.codes website",
 "Resources": {
 "Role": {
 "Type": "AWS::IAM::Role",
 "Properties": {
 "AssumeRolePolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": {
 "Service": "lambda.amazonaws.com"
 },
 "Action": "sts:AssumeRole"
 }
 ]
 },
 "Policies": [
 {
 "PolicyName": "ArcGlobalPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "logs:CreateLogGroup",
 "logs:CreateLogStream",
 "logs:PutLogEvents",
 "logs:DescribeLogStreams"
 ],
 "Resource": "arn:aws:logs:*:*:*"
 }
 ]
 }
 },
 {
 "PolicyName": "ArcStaticBucketPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:PutObjectAcl",
 "s3:DeleteObject",
 "s3:ListBucket"
 ],
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ]
 }
 ]
 }
 }
 ]
 }
 },
 "StaticBucketParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "bucket"
 }
 ]
 },
 "Value": {
 "Ref": "StaticBucket"
 }
 }
 },
 "StaticFingerprintParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "fingerprint"
 }
 ]
 },
 "Value": "true"
 }
 },
 "ParameterStorePolicy": {
 "Type": "AWS::IAM::Policy",
 "DependsOn": "Role",
 "Properties": {
 "PolicyName": "ArcParameterStorePolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*/*",
 {}
 ]
 }
 }
 ]
 },
 "Roles": [
 {
 "Ref": "Role"
 }
 ]
 }
 },
 "HTTP": {
 "Type": "AWS::Serverless::HttpApi",
 "Properties": {
 "StageName": "$default",
 "DefinitionBody": {
 "openapi": "3.0.1",
 "info": {
 "title": {
 "Ref": "AWS::StackName"
 }
 },
 "paths": {
 "/docs/{lang}/{proxy+}": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetDocsLangCatchallHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/api/package": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetApiPackageHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/landing": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetLandingHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/{proxy+}": {
 "x-amazon-apigateway-any-method": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AnyCatchallHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/_static/{proxy+}": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "1.0",
 "type": "http_proxy",
 "httpMethod": "GET",
 "uri": {
 "Fn::Sub": [
 "https://${bukkit}.s3.${AWS::Region}.amazonaws.com/{proxy}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 "connectionType": "INTERNET",
 "timeoutInMillis": 30000
 }
 }
 }
 }
 }
 }
 },
 "GetDocsLangCatchallHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-docs-000lang-catchall",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "arc-codes",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetDocsLangCatchallHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/docs/{lang}/{proxy+}",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /docs/:lang/*",
 "method": "get",
 "path": "/docs/:lang/*"
 }
 },
 "GetApiPackageHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-api-package",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "arc-codes",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetApiPackageHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/api/package",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /api/package",
 "method": "get",
 "path": "/api/package"
 }
 },
 "GetLandingHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-landing",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "arc-codes",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetLandingHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/landing",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /landing",
 "method": "get",
 "path": "/landing"
 }
 },
 "AnyCatchallHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/any-catchall",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "arc-codes",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_STATIC_SPA": false
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "AnyCatchallHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/{proxy+}",
 "Method": "ANY",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "any /*",
 "method": "any",
 "path": "/*"
 }
 },
 "StaticBucket": {
 "Type": "AWS::S3::Bucket",
 "Properties": {
 "OwnershipControls": {
 "Rules": [
 {
 "ObjectOwnership": "BucketOwnerEnforced"
 }
 ]
 },
 "WebsiteConfiguration": {
 "IndexDocument": "index.html",
 "ErrorDocument": "404.html"
 },
 "PublicAccessBlockConfiguration": {
 "BlockPublicAcls": false,
 "BlockPublicPolicy": false,
 "IgnorePublicAcls": false,
 "RestrictPublicBuckets": false
 }
 }
 },
 "StaticBucketPolicy": {
 "Type": "AWS::S3::BucketPolicy",
 "Properties": {
 "Bucket": {
 "Ref": "StaticBucket"
 },
 "PolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Action": [
 "s3:GetObject"
 ],
 "Effect": "Allow",
 "Principal": "*",
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ],
 "Sid": "PublicReadGetObject"
 }
 ]
 }
 }
 }
 },
 "Outputs": {
 "API": {
 "Description": "API Gateway (HTTP)",
 "Value": {
 "Fn::Sub": [
 "https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com",
 {
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 ]
 }
 },
 "ApiId": {
 "Description": "API ID (ApiId)",
 "Value": {
 "Ref": "HTTP"
 }
 },
 "BucketURL": {
 "Description": "Bucket URL",
 "Value": {
 "Fn::Sub": [
 "http://${bukkit}.s3-website-${AWS::Region}.amazonaws.com",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 }
 }
}

Architect manifest

25 lines of config

@appkitchen-sink@staticfingerprinttrue@httpget/get/likespost/likes@tableslikes
 likeID *String@tables-streamslikes@tables-indexeslikes
 date *String@wsactionconnectdefaultdisconnect@eventshit-counter@scheduleddaily-affirmationrate(1day)

CloudFormation

1,385 lines of IaC template

{
 "AWSTemplateFormatVersion": "2010-09-09",
 "Transform": "AWS::Serverless-2016年10月31日",
 "Description": "Example: kitchen sink",
 "Resources": {
 "Role": {
 "Type": "AWS::IAM::Role",
 "Properties": {
 "AssumeRolePolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": {
 "Service": "lambda.amazonaws.com"
 },
 "Action": "sts:AssumeRole"
 }
 ]
 },
 "Policies": [
 {
 "PolicyName": "ArcGlobalPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "logs:CreateLogGroup",
 "logs:CreateLogStream",
 "logs:PutLogEvents",
 "logs:DescribeLogStreams"
 ],
 "Resource": "arn:aws:logs:*:*:*"
 }
 ]
 }
 },
 {
 "PolicyName": "ArcStaticBucketPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:PutObjectAcl",
 "s3:DeleteObject",
 "s3:ListBucket"
 ],
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ]
 }
 ]
 }
 },
 {
 "PolicyName": "ArcDynamoPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": "dynamodb:*",
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}",
 {
 "tablename": {
 "Ref": "LikesTable"
 }
 }
 ]
 },
 {
 "Fn::Sub": [
 "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*",
 {
 "tablename": {
 "Ref": "LikesTable"
 }
 }
 ]
 }
 ]
 },
 {
 "Effect": "Deny",
 "Action": "dynamodb:DeleteTable",
 "Resource": {
 "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/*"
 }
 }
 ]
 }
 },
 {
 "PolicyName": "ArcSimpleNotificationServicePolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "sns:Publish"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}*",
 {}
 ]
 }
 }
 ]
 }
 }
 ]
 }
 },
 "LikesParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/tables/${tablename}",
 {
 "tablename": "likes"
 }
 ]
 },
 "Value": {
 "Ref": "LikesTable"
 }
 }
 },
 "HitCounterEventTopicParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/events/${event}",
 {
 "event": "hit-counter"
 }
 ]
 },
 "Value": {
 "Ref": "HitCounterEventTopic"
 }
 }
 },
 "StaticBucketParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "bucket"
 }
 ]
 },
 "Value": {
 "Ref": "StaticBucket"
 }
 }
 },
 "StaticFingerprintParam": {
 "Type": "AWS::SSM::Parameter",
 "Properties": {
 "Type": "String",
 "Name": {
 "Fn::Sub": [
 "/${AWS::StackName}/static/${key}",
 {
 "key": "fingerprint"
 }
 ]
 },
 "Value": "true"
 }
 },
 "ParameterStorePolicy": {
 "Type": "AWS::IAM::Policy",
 "DependsOn": "Role",
 "Properties": {
 "PolicyName": "ArcParameterStorePolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*",
 {}
 ]
 }
 },
 {
 "Effect": "Allow",
 "Action": [
 "ssm:GetParametersByPath",
 "ssm:GetParameter"
 ],
 "Resource": {
 "Fn::Sub": [
 "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${AWS::StackName}/*/*",
 {}
 ]
 }
 }
 ]
 },
 "Roles": [
 {
 "Ref": "Role"
 }
 ]
 }
 },
 "HTTP": {
 "Type": "AWS::Serverless::HttpApi",
 "Properties": {
 "StageName": "$default",
 "DefinitionBody": {
 "openapi": "3.0.1",
 "info": {
 "title": {
 "Ref": "AWS::StackName"
 }
 },
 "paths": {
 "/likes": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetLikesHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 },
 "post": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PostLikesHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "2.0",
 "type": "aws_proxy",
 "httpMethod": "POST",
 "uri": {
 "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetIndexHTTPLambda.Arn}/invocations"
 },
 "connectionType": "INTERNET"
 }
 }
 },
 "/_static/{proxy+}": {
 "get": {
 "x-amazon-apigateway-integration": {
 "payloadFormatVersion": "1.0",
 "type": "http_proxy",
 "httpMethod": "GET",
 "uri": {
 "Fn::Sub": [
 "https://${bukkit}.s3.${AWS::Region}.amazonaws.com/{proxy}",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 },
 "connectionType": "INTERNET",
 "timeoutInMillis": 30000
 }
 }
 }
 }
 }
 }
 },
 "GetLikesHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-likes",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetLikesHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/likes",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /likes",
 "method": "get",
 "path": "/likes"
 }
 },
 "GetIndexHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/get-index",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 },
 "ARC_STATIC_SPA": false
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "GetIndexHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/",
 "Method": "GET",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "get /",
 "method": "get",
 "path": "/"
 }
 },
 "PostLikesHTTPLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/http/post-likes",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "PostLikesHTTPEvent": {
 "Type": "HttpApi",
 "Properties": {
 "Path": "/likes",
 "Method": "POST",
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "http",
 "name": "post /likes",
 "method": "post",
 "path": "/likes"
 }
 },
 "LikesTable": {
 "Type": "AWS::DynamoDB::Table",
 "Properties": {
 "KeySchema": [
 {
 "AttributeName": "likeID",
 "KeyType": "HASH"
 }
 ],
 "AttributeDefinitions": [
 {
 "AttributeName": "likeID",
 "AttributeType": "S"
 },
 {
 "AttributeName": "date",
 "AttributeType": "S"
 }
 ],
 "BillingMode": "PAY_PER_REQUEST",
 "GlobalSecondaryIndexes": [
 {
 "IndexName": "date-index",
 "KeySchema": [
 {
 "AttributeName": "date",
 "KeyType": "HASH"
 }
 ],
 "Projection": {
 "ProjectionType": "ALL"
 }
 }
 ],
 "StreamSpecification": {
 "StreamViewType": "NEW_AND_OLD_IMAGES"
 }
 }
 },
 "HitCounterEventLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/events/hit-counter",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {
 "HitCounterEvent": {
 "Type": "SNS",
 "Properties": {
 "Topic": {
 "Ref": "HitCounterEventTopic"
 }
 }
 }
 }
 },
 "ArcMetadata": {
 "pragma": "events",
 "name": "hit-counter"
 }
 },
 "HitCounterEventTopic": {
 "Type": "AWS::SNS::Topic",
 "Properties": {
 "DisplayName": "HitCounter",
 "Subscription": []
 }
 },
 "DailyAffirmationScheduledLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/scheduled/daily-affirmation",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "scheduled",
 "name": "daily-affirmation"
 }
 },
 "DailyAffirmationScheduledEvent": {
 "Type": "AWS::Events::Rule",
 "Properties": {
 "ScheduleExpression": "rate(1 day)",
 "Targets": [
 {
 "Arn": {
 "Fn::GetAtt": [
 "DailyAffirmationScheduledLambda",
 "Arn"
 ]
 },
 "Id": "DailyAffirmationScheduledLambda"
 }
 ]
 }
 },
 "DailyAffirmationScheduledPermission": {
 "Type": "AWS::Lambda::Permission",
 "Properties": {
 "Action": "lambda:InvokeFunction",
 "FunctionName": {
 "Ref": "DailyAffirmationScheduledLambda"
 },
 "Principal": "events.amazonaws.com",
 "SourceArn": {
 "Fn::GetAtt": [
 "DailyAffirmationScheduledEvent",
 "Arn"
 ]
 }
 }
 },
 "StaticBucket": {
 "Type": "AWS::S3::Bucket",
 "Properties": {
 "OwnershipControls": {
 "Rules": [
 {
 "ObjectOwnership": "BucketOwnerEnforced"
 }
 ]
 },
 "WebsiteConfiguration": {
 "IndexDocument": "index.html",
 "ErrorDocument": "404.html"
 },
 "PublicAccessBlockConfiguration": {
 "BlockPublicAcls": false,
 "BlockPublicPolicy": false,
 "IgnorePublicAcls": false,
 "RestrictPublicBuckets": false
 }
 }
 },
 "StaticBucketPolicy": {
 "Type": "AWS::S3::BucketPolicy",
 "Properties": {
 "Bucket": {
 "Ref": "StaticBucket"
 },
 "PolicyDocument": {
 "Version": "2012-10-17",
 "Statement": [
 {
 "Action": [
 "s3:GetObject"
 ],
 "Effect": "Allow",
 "Principal": "*",
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:s3:::${bukkit}/*",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 ],
 "Sid": "PublicReadGetObject"
 }
 ]
 }
 }
 },
 "LikesTableStreamLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/tables-streams/likes",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "tables-streams",
 "name": "likes"
 }
 },
 "LikesTableStreamEvent": {
 "Type": "AWS::Lambda::EventSourceMapping",
 "Properties": {
 "BatchSize": 10,
 "EventSourceArn": {
 "Fn::GetAtt": [
 "LikesTable",
 "StreamArn"
 ]
 },
 "FunctionName": {
 "Fn::GetAtt": [
 "LikesTableStreamLambda",
 "Arn"
 ]
 },
 "StartingPosition": "TRIM_HORIZON"
 }
 },
 "WS": {
 "Type": "AWS::ApiGatewayV2::Api",
 "Properties": {
 "Name": "HelloWebsocketStaging",
 "ProtocolType": "WEBSOCKET",
 "RouteSelectionExpression": "$request.body.action"
 }
 },
 "WebsocketDeployment": {
 "Type": "AWS::ApiGatewayV2::Deployment",
 "DependsOn": [
 "ConnectWSRoute",
 "DefaultWSRoute",
 "DisconnectWSRoute"
 ],
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 }
 }
 },
 "WebsocketStage": {
 "Type": "AWS::ApiGatewayV2::Stage",
 "Properties": {
 "StageName": "staging",
 "DeploymentId": {
 "Ref": "WebsocketDeployment"
 },
 "ApiId": {
 "Ref": "WS"
 }
 }
 },
 "WebSocketPolicy": {
 "Type": "AWS::IAM::Policy",
 "DependsOn": "Role",
 "Properties": {
 "PolicyName": "ArcWebSocketPolicy",
 "PolicyDocument": {
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "execute-api:Invoke",
 "execute-api:ManageConnections"
 ],
 "Resource": [
 {
 "Fn::Sub": [
 "arn:aws:execute-api:${AWS::Region}:*:${api}/*",
 {
 "api": {
 "Ref": "WS"
 }
 }
 ]
 }
 ]
 }
 ]
 },
 "Roles": [
 {
 "Ref": "Role"
 }
 ]
 }
 },
 "ActionWSLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/ws/action",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "ws",
 "name": "action"
 }
 },
 "ActionWSRoute": {
 "Type": "AWS::ApiGatewayV2::Route",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "RouteKey": "action",
 "OperationName": "ActionWSRoute",
 "Target": {
 "Fn::Join": [
 "/",
 [
 "integrations",
 {
 "Ref": "ActionWSIntegration"
 }
 ]
 ]
 }
 }
 },
 "ActionWSIntegration": {
 "Type": "AWS::ApiGatewayV2::Integration",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "IntegrationType": "AWS_PROXY",
 "IntegrationUri": {
 "Fn::Sub": [
 "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ActionWSLambda.Arn}/invocations",
 {}
 ]
 }
 }
 },
 "ActionWSPermission": {
 "Type": "AWS::Lambda::Permission",
 "DependsOn": [
 "WS",
 "ActionWSLambda"
 ],
 "Properties": {
 "Action": "lambda:InvokeFunction",
 "FunctionName": {
 "Ref": "ActionWSLambda"
 },
 "Principal": "apigateway.amazonaws.com"
 }
 },
 "ConnectWSLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/ws/connect",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "ws",
 "name": "connect"
 }
 },
 "ConnectWSRoute": {
 "Type": "AWS::ApiGatewayV2::Route",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "RouteKey": "$connect",
 "OperationName": "ConnectWSRoute",
 "Target": {
 "Fn::Join": [
 "/",
 [
 "integrations",
 {
 "Ref": "ConnectWSIntegration"
 }
 ]
 ]
 }
 }
 },
 "ConnectWSIntegration": {
 "Type": "AWS::ApiGatewayV2::Integration",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "IntegrationType": "AWS_PROXY",
 "IntegrationUri": {
 "Fn::Sub": [
 "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ConnectWSLambda.Arn}/invocations",
 {}
 ]
 }
 }
 },
 "ConnectWSPermission": {
 "Type": "AWS::Lambda::Permission",
 "DependsOn": [
 "WS",
 "ConnectWSLambda"
 ],
 "Properties": {
 "Action": "lambda:InvokeFunction",
 "FunctionName": {
 "Ref": "ConnectWSLambda"
 },
 "Principal": "apigateway.amazonaws.com"
 }
 },
 "DefaultWSLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/ws/default",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "ws",
 "name": "default"
 }
 },
 "DefaultWSRoute": {
 "Type": "AWS::ApiGatewayV2::Route",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "RouteKey": "$default",
 "OperationName": "DefaultWSRoute",
 "Target": {
 "Fn::Join": [
 "/",
 [
 "integrations",
 {
 "Ref": "DefaultWSIntegration"
 }
 ]
 ]
 }
 }
 },
 "DefaultWSIntegration": {
 "Type": "AWS::ApiGatewayV2::Integration",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "IntegrationType": "AWS_PROXY",
 "IntegrationUri": {
 "Fn::Sub": [
 "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DefaultWSLambda.Arn}/invocations",
 {}
 ]
 }
 }
 },
 "DefaultWSPermission": {
 "Type": "AWS::Lambda::Permission",
 "DependsOn": [
 "WS",
 "DefaultWSLambda"
 ],
 "Properties": {
 "Action": "lambda:InvokeFunction",
 "FunctionName": {
 "Ref": "DefaultWSLambda"
 },
 "Principal": "apigateway.amazonaws.com"
 }
 },
 "DisconnectWSLambda": {
 "Type": "AWS::Serverless::Function",
 "Properties": {
 "Handler": "index.handler",
 "CodeUri": "/var/task/src/ws/disconnect",
 "Runtime": "nodejs20.x",
 "Architectures": [
 "arm64"
 ],
 "MemorySize": 1152,
 "EphemeralStorage": {
 "Size": 512
 },
 "Timeout": 5,
 "Environment": {
 "Variables": {
 "ARC_APP_NAME": "hello",
 "ARC_ENV": "staging",
 "ARC_ROLE": {
 "Ref": "Role"
 },
 "ARC_SESSION_TABLE_NAME": "jwe",
 "ARC_STACK_NAME": {
 "Ref": "AWS::StackName"
 },
 "ARC_STATIC_BUCKET": {
 "Ref": "StaticBucket"
 },
 "ARC_WSS_URL": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 },
 "Role": {
 "Fn::Sub": [
 "arn:aws:iam::${AWS::AccountId}:role/${roleName}",
 {
 "roleName": {
 "Ref": "Role"
 }
 }
 ]
 },
 "Events": {}
 },
 "ArcMetadata": {
 "pragma": "ws",
 "name": "disconnect"
 }
 },
 "DisconnectWSRoute": {
 "Type": "AWS::ApiGatewayV2::Route",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "RouteKey": "$disconnect",
 "OperationName": "DisconnectWSRoute",
 "Target": {
 "Fn::Join": [
 "/",
 [
 "integrations",
 {
 "Ref": "DisconnectWSIntegration"
 }
 ]
 ]
 }
 }
 },
 "DisconnectWSIntegration": {
 "Type": "AWS::ApiGatewayV2::Integration",
 "Properties": {
 "ApiId": {
 "Ref": "WS"
 },
 "IntegrationType": "AWS_PROXY",
 "IntegrationUri": {
 "Fn::Sub": [
 "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DisconnectWSLambda.Arn}/invocations",
 {}
 ]
 }
 }
 },
 "DisconnectWSPermission": {
 "Type": "AWS::Lambda::Permission",
 "DependsOn": [
 "WS",
 "DisconnectWSLambda"
 ],
 "Properties": {
 "Action": "lambda:InvokeFunction",
 "FunctionName": {
 "Ref": "DisconnectWSLambda"
 },
 "Principal": "apigateway.amazonaws.com"
 }
 }
 },
 "Outputs": {
 "API": {
 "Description": "API Gateway (HTTP)",
 "Value": {
 "Fn::Sub": [
 "https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com",
 {
 "ApiId": {
 "Ref": "HTTP"
 }
 }
 ]
 }
 },
 "ApiId": {
 "Description": "API ID (ApiId)",
 "Value": {
 "Ref": "HTTP"
 }
 },
 "HitCounterEventTopic": {
 "Description": "An SNS Topic",
 "Value": {
 "Ref": "HitCounterEventTopic"
 }
 },
 "BucketURL": {
 "Description": "Bucket URL",
 "Value": {
 "Fn::Sub": [
 "http://${bukkit}.s3-website-${AWS::Region}.amazonaws.com",
 {
 "bukkit": {
 "Ref": "StaticBucket"
 }
 }
 ]
 }
 },
 "WSS": {
 "Description": "WebSocket Endpoint",
 "Value": {
 "Fn::Sub": [
 "wss://${WS}.execute-api.${AWS::Region}.amazonaws.com/staging",
 {}
 ]
 }
 }
 }
}

Ditch the complexity and vendor cruft. Get started with Architect today.

Read the quick start

AltStyle によって変換されたページ (->オリジナル) /