@thunder-so/thunder 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/CLI.md +65 -0
- package/.agents/METADATA.md +75 -0
- package/.agents/PRD.md +537 -0
- package/.agents/SKILLS.md +543 -0
- package/README.md +409 -0
- package/bun.lock +425 -0
- package/cli/th.mjs +45 -0
- package/index.ts +25 -0
- package/package.json +63 -0
- package/runtime/Dockerfile +44 -0
- package/thunder-so-thunder-1.1.0.tgz +0 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# thunder
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://www.npmjs.com/package/@thunder-so/thunder"><img alt="Version" src="https://img.shields.io/npm/v/@thunder-so/thunder.svg" /></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/@thunder-so/thunder"><img alt="License" src="https://img.shields.io/npm/l/@thunder-so/thunder.svg" /></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
Build full-stack apps on your own AWS.
|
|
9
|
+
|
|
10
|
+
Thunder is a CDK library and CLI for deploying modern web applications on AWS. One library to rule them all: [Static SPAs](#static), [Lambda Functions](#lambda), [Containers on Fargate](#fargate) and [EC2](#ec2), and [Full-stack Frameworks](#full-stack-frameworks).
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#features)
|
|
15
|
+
- [Supported Frameworks & Patterns](#supported-frameworks--patterns)
|
|
16
|
+
- [Quick Start](#quick-start)
|
|
17
|
+
- [Stacks](#stacks)
|
|
18
|
+
- [Static](#static) - S3 + CloudFront + Route53
|
|
19
|
+
- [Lambda](#lambda) - API Gateway + Lambda
|
|
20
|
+
- [Fargate](#fargate) - ECS Fargate + ALB + CloudFront
|
|
21
|
+
- [EC2](#ec2) - EC2 + Docker + Elastic IP
|
|
22
|
+
- [Nuxt](#nuxt) - Serverless full-stack with Lambda
|
|
23
|
+
- [Astro](#astro) - Serverless full-stack SSR with Lambda
|
|
24
|
+
- [Template](#template) - Coolify-style templates
|
|
25
|
+
- [CLI Commands](#cli-commands)
|
|
26
|
+
- [Documentation](#documentation)
|
|
27
|
+
- [License](#license)
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Constructs:** One-line deployment for `Static`, `Lambda`, `Fargate`, `EC2`, `Nuxt`, and `Astro`.
|
|
32
|
+
- **Thunder CLI (`th`):** Context-aware CLI for initializing, deploying, and managing your infrastructure.
|
|
33
|
+
- **VPC Link Pattern:** Easily connect your compute resources to a shared VPC.
|
|
34
|
+
- **High-Performance Serving:** Pre-configured [CloudFront](https://aws.amazon.com/cloudfront/) distributions with OAC, security headers, and edge optimizations.
|
|
35
|
+
- **Built-in CI/CD:** Optional [AWS CodePipeline](https://aws.amazon.com/codepipeline/) integration with GitHub support.
|
|
36
|
+
|
|
37
|
+
## Supported Frameworks & Patterns
|
|
38
|
+
|
|
39
|
+
- **Static:** Vite (React, Vue, Svelte, Solid), Next.js (SSG), Astro (SSG), Gatsby.
|
|
40
|
+
- **Serverless:** Node.js Lambda, Bun, Container-based Lambda.
|
|
41
|
+
- **Containers:** [ECS Fargate](https://aws.amazon.com/fargate/) with ALB, Docker on [EC2](https://aws.amazon.com/ec2/) with Elastic IP.
|
|
42
|
+
- **Full-stack SSR:** [Nuxt.js](https://nuxt.com/), [Astro](https://astro.build/) (SSR), and extensibility for SvelteKit, TanStack Start, AnalogJS.
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
### 1. Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bun add @thunder-so/thunder --development
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Initialize
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx th init
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Configure
|
|
59
|
+
|
|
60
|
+
Create a stack file (e.g., `stack/dev.ts`):
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { Cdk, Static, type StaticProps } from '@thunder-so/thunder';
|
|
64
|
+
|
|
65
|
+
const myApp: StaticProps = {
|
|
66
|
+
env: {
|
|
67
|
+
account: '123456789012',
|
|
68
|
+
region: 'us-east-1'
|
|
69
|
+
},
|
|
70
|
+
application: 'myapp',
|
|
71
|
+
service: 'web',
|
|
72
|
+
environment: 'prod',
|
|
73
|
+
|
|
74
|
+
rootDir: '.',
|
|
75
|
+
outputDir: 'dist',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
new Static(
|
|
79
|
+
new Cdk.App(),
|
|
80
|
+
`${myApp.application}-${myApp.service}-${myApp.environment}-stack`,
|
|
81
|
+
myApp
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 4. Deploy
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx cdk deploy --app "npx tsx stack/dev.ts" --profile default
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Stacks
|
|
92
|
+
|
|
93
|
+
### Static
|
|
94
|
+
|
|
95
|
+
Deploy static websites to [S3](https://aws.amazon.com/s3/) with [CloudFront](https://aws.amazon.com/cloudfront/) CDN and [Route53](https://aws.amazon.com/route53/) DNS.
|
|
96
|
+
|
|
97
|
+
**Best for:** Static sites, SPAs, JAMstack applications
|
|
98
|
+
|
|
99
|
+
**AWS Resources:**
|
|
100
|
+
- [S3 Bucket](https://aws.amazon.com/s3/) - Static file hosting
|
|
101
|
+
- [CloudFront Distribution](https://aws.amazon.com/cloudfront/) - Global CDN with caching
|
|
102
|
+
- [Route53](https://aws.amazon.com/route53/) - DNS management (optional)
|
|
103
|
+
- [ACM Certificate](https://aws.amazon.com/certificate-manager/) - SSL/TLS certificates (optional)
|
|
104
|
+
- [Lambda@Edge](https://aws.amazon.com/lambda/edge/) - Request/response manipulation (optional)
|
|
105
|
+
|
|
106
|
+
**Example:**
|
|
107
|
+
```typescript
|
|
108
|
+
import { Cdk, Static, type StaticProps } from '@thunder-so/thunder';
|
|
109
|
+
|
|
110
|
+
const config: StaticProps = {
|
|
111
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
112
|
+
application: 'myapp',
|
|
113
|
+
service: 'web',
|
|
114
|
+
environment: 'prod',
|
|
115
|
+
rootDir: '.',
|
|
116
|
+
outputDir: 'dist',
|
|
117
|
+
|
|
118
|
+
// Optional: Custom domain
|
|
119
|
+
domain: 'example.com',
|
|
120
|
+
globalCertificateArn: 'arn:aws:acm:us-east-1:...',
|
|
121
|
+
hostedZoneId: 'Z123456789',
|
|
122
|
+
|
|
123
|
+
// Optional: Lambda@Edge for redirects/headers/rewrites
|
|
124
|
+
redirects: [{ source: '/old', destination: '/' }],
|
|
125
|
+
rewrites: [{ source: '/old', destination: '/new' }],
|
|
126
|
+
headers: [{ path: '/*', name: 'X-Custom-Header', value: 'value' }],
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
new Static(new Cdk.App(), 'myapp-web-prod-stack', config);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### Lambda
|
|
135
|
+
|
|
136
|
+
Deploy serverless functions with [API Gateway](https://aws.amazon.com/api-gateway/) and optional [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html).
|
|
137
|
+
|
|
138
|
+
**Best for:** Serverless APIs, microservices, event-driven applications
|
|
139
|
+
|
|
140
|
+
**AWS Resources:**
|
|
141
|
+
- [Lambda Function](https://aws.amazon.com/lambda/) - Compute layer
|
|
142
|
+
- [API Gateway](https://aws.amazon.com/api-gateway/) - HTTP API with custom domain support
|
|
143
|
+
- [CloudWatch Logs](https://aws.amazon.com/cloudwatch/) - Logging and monitoring
|
|
144
|
+
- [Secrets Manager](https://aws.amazon.com/secrets-manager/) - Secure secret injection (optional)
|
|
145
|
+
|
|
146
|
+
**Example:**
|
|
147
|
+
```typescript
|
|
148
|
+
import { Cdk, Lambda, type LambdaProps } from '@thunder-so/thunder';
|
|
149
|
+
|
|
150
|
+
const config: LambdaProps = {
|
|
151
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
152
|
+
application: 'myapp',
|
|
153
|
+
service: 'api',
|
|
154
|
+
environment: 'prod',
|
|
155
|
+
rootDir: '.',
|
|
156
|
+
|
|
157
|
+
functionProps: {
|
|
158
|
+
runtime: Cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
159
|
+
architecture: Cdk.aws_lambda.Architecture.ARM_64,
|
|
160
|
+
codeDir: 'src',
|
|
161
|
+
handler: 'index.handler',
|
|
162
|
+
memorySize: 512,
|
|
163
|
+
timeout: 30,
|
|
164
|
+
url: true, // Enable function URL
|
|
165
|
+
keepWarm: true, // Prevent cold starts
|
|
166
|
+
variables: [{ NODE_ENV: 'production' }],
|
|
167
|
+
secrets: [{ key: 'DATABASE_URL', resource: 'arn:aws:secretsmanager:...' }],
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
// Optional: Custom domain
|
|
171
|
+
domain: 'api.example.com',
|
|
172
|
+
regionalCertificateArn: 'arn:aws:acm:us-east-1:...',
|
|
173
|
+
hostedZoneId: 'Z123456789',
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
new Lambda(new Cdk.App(), 'myapp-api-prod-stack', config);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### Fargate
|
|
182
|
+
|
|
183
|
+
Deploy containerized applications on [ECS Fargate](https://aws.amazon.com/fargate/) with Application Load Balancer and [CloudFront](https://aws.amazon.com/cloudfront/).
|
|
184
|
+
|
|
185
|
+
**Best for:** Containerized web applications, microservices, long-running processes
|
|
186
|
+
|
|
187
|
+
**AWS Resources:**
|
|
188
|
+
- [ECS Cluster](https://aws.amazon.com/ecs/) - Container orchestration
|
|
189
|
+
- [Fargate Task](https://aws.amazon.com/fargate/) - Serverless containers
|
|
190
|
+
- [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/) - Traffic distribution
|
|
191
|
+
- [ECR Repository](https://aws.amazon.com/ecr/) - Container registry (via CodePipeline)
|
|
192
|
+
- [CloudWatch Logs](https://aws.amazon.com/cloudwatch/) - Container logging
|
|
193
|
+
|
|
194
|
+
**Example:**
|
|
195
|
+
```typescript
|
|
196
|
+
import { Cdk, Fargate, type FargateProps } from '@thunder-so/thunder';
|
|
197
|
+
|
|
198
|
+
const config: FargateProps = {
|
|
199
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
200
|
+
application: 'myapp',
|
|
201
|
+
service: 'api',
|
|
202
|
+
environment: 'prod',
|
|
203
|
+
rootDir: '.',
|
|
204
|
+
|
|
205
|
+
serviceProps: {
|
|
206
|
+
architecture: Cdk.aws_ecs.CpuArchitecture.ARM64,
|
|
207
|
+
desiredCount: 2,
|
|
208
|
+
cpu: 512, // 0.5 vCPU
|
|
209
|
+
memorySize: 1024, // 1 GB
|
|
210
|
+
port: 3000,
|
|
211
|
+
healthCheckPath: '/health',
|
|
212
|
+
variables: [{ NODE_ENV: 'production' }],
|
|
213
|
+
dockerFile: 'Dockerfile',
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
// Optional: Custom domain
|
|
217
|
+
domain: 'api.example.com',
|
|
218
|
+
globalCertificateArn: 'arn:aws:acm:us-east-1:...',
|
|
219
|
+
hostedZoneId: 'Z123456789',
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
new Fargate(new Cdk.App(), 'myapp-api-prod-stack', config);
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### EC2
|
|
228
|
+
|
|
229
|
+
Deploy Docker containers on [EC2](https://aws.amazon.com/ec2/) instances with Elastic IP for simple, cost-effective hosting.
|
|
230
|
+
|
|
231
|
+
**Best for:** Single-instance applications, development environments, simple Docker deployments
|
|
232
|
+
|
|
233
|
+
**AWS Resources:**
|
|
234
|
+
- [EC2 Instance](https://aws.amazon.com/ec2/) - Virtual server
|
|
235
|
+
- [Elastic IP](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) - Static public IP
|
|
236
|
+
- [VPC](https://aws.amazon.com/vpc/) - Network isolation
|
|
237
|
+
- [Security Group](https://docs.aws.amazon.com/vpc/latest/userguide/security-groups.html) - Firewall rules
|
|
238
|
+
- [Route53](https://aws.amazon.com/route53/) - DNS records (optional)
|
|
239
|
+
|
|
240
|
+
**Example:**
|
|
241
|
+
```typescript
|
|
242
|
+
import { Cdk, Ec2, type Ec2Props } from '@thunder-so/thunder';
|
|
243
|
+
|
|
244
|
+
const config: Ec2Props = {
|
|
245
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
246
|
+
application: 'myapp',
|
|
247
|
+
service: 'api',
|
|
248
|
+
environment: 'prod',
|
|
249
|
+
rootDir: '.',
|
|
250
|
+
|
|
251
|
+
serviceProps: {
|
|
252
|
+
instanceType: 't3.micro',
|
|
253
|
+
port: 3000,
|
|
254
|
+
authorizedKeys: ['ssh-rsa AAAAB3... user@example.com'],
|
|
255
|
+
dockerFile: 'Dockerfile',
|
|
256
|
+
variables: [{ NODE_ENV: 'production' }],
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
// Optional: Custom domain with SSL
|
|
260
|
+
domain: 'api.example.com',
|
|
261
|
+
hostedZoneId: 'Z123456789',
|
|
262
|
+
acmeEmail: 'admin@example.com', // For Let's Encrypt
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
new Ec2(new Cdk.App(), 'myapp-api-prod-stack', config);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Full-Stack Frameworks
|
|
271
|
+
|
|
272
|
+
#### Nuxt
|
|
273
|
+
|
|
274
|
+
Deploy [Nuxt.js](https://nuxt.com/) SSR applications with hybrid rendering - Lambda for server-side and S3 for static assets.
|
|
275
|
+
|
|
276
|
+
**Best for:** Vue-based full-stack applications with server-side rendering
|
|
277
|
+
|
|
278
|
+
**AWS Resources:**
|
|
279
|
+
- [Lambda Function](https://aws.amazon.com/lambda/) - SSR server
|
|
280
|
+
- [S3 Bucket](https://aws.amazon.com/s3/) - Static assets
|
|
281
|
+
- [CloudFront Distribution](https://aws.amazon.com/cloudfront/) - Unified CDN
|
|
282
|
+
- [API Gateway](https://aws.amazon.com/api-gateway/) - HTTP API
|
|
283
|
+
|
|
284
|
+
**Example:**
|
|
285
|
+
```typescript
|
|
286
|
+
import { Cdk, Nuxt, type NuxtProps } from '@thunder-so/thunder';
|
|
287
|
+
|
|
288
|
+
const config: NuxtProps = {
|
|
289
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
290
|
+
application: 'myapp',
|
|
291
|
+
service: 'web',
|
|
292
|
+
environment: 'prod',
|
|
293
|
+
rootDir: '.',
|
|
294
|
+
|
|
295
|
+
serverProps: {
|
|
296
|
+
runtime: Cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
297
|
+
architecture: Cdk.aws_lambda.Architecture.ARM_64,
|
|
298
|
+
memorySize: 1792,
|
|
299
|
+
timeout: 10,
|
|
300
|
+
keepWarm: true,
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
// Optional: Custom domain
|
|
304
|
+
domain: 'example.com',
|
|
305
|
+
globalCertificateArn: 'arn:aws:acm:us-east-1:...',
|
|
306
|
+
hostedZoneId: 'Z123456789',
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
new Nuxt(new Cdk.App(), 'myapp-web-prod-stack', config);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
#### Astro
|
|
315
|
+
|
|
316
|
+
Deploy [Astro](https://astro.build/) SSR applications with the same infrastructure pattern as Nuxt.
|
|
317
|
+
|
|
318
|
+
**Best for:** Content-focused websites with server-side rendering and islands architecture
|
|
319
|
+
|
|
320
|
+
**AWS Resources:** Same as [Nuxt](#nuxt)
|
|
321
|
+
|
|
322
|
+
**Example:**
|
|
323
|
+
```typescript
|
|
324
|
+
import { Cdk, Astro, type NuxtProps as AstroProps } from '@thunder-so/thunder';
|
|
325
|
+
|
|
326
|
+
const config: AstroProps = {
|
|
327
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
328
|
+
application: 'myapp',
|
|
329
|
+
service: 'web',
|
|
330
|
+
environment: 'prod',
|
|
331
|
+
rootDir: '.',
|
|
332
|
+
|
|
333
|
+
serverProps: {
|
|
334
|
+
runtime: Cdk.aws_lambda.Runtime.NODEJS_22_X,
|
|
335
|
+
architecture: Cdk.aws_lambda.Architecture.ARM_64,
|
|
336
|
+
memorySize: 1024,
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
new Astro(new Cdk.App(), 'myapp-web-prod-stack', config);
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
### Template
|
|
346
|
+
|
|
347
|
+
Deploy [Coolify](https://coolify.io/)-style templates on EC2. Automatically fetches and hydrates Docker Compose templates from the [Coolify templates repository](https://github.com/coollabsio/coolify).
|
|
348
|
+
|
|
349
|
+
**Best for:** Self-hosted applications, databases, dev tools (e.g., n8n, WordPress, databases)
|
|
350
|
+
|
|
351
|
+
**AWS Resources:** Same as [EC2](#ec2)
|
|
352
|
+
|
|
353
|
+
**Example:**
|
|
354
|
+
```typescript
|
|
355
|
+
import { Cdk, Template, type TemplateProps, fetchTemplate, hydrateTemplate } from '@thunder-so/thunder';
|
|
356
|
+
import { InstanceType, InstanceClass, InstanceSize } from 'aws-cdk-lib/aws-ec2';
|
|
357
|
+
|
|
358
|
+
async function main() {
|
|
359
|
+
// Fetch template from Coolify repository
|
|
360
|
+
const { parsed: parsedTemplate, port } = await fetchTemplate('n8n');
|
|
361
|
+
|
|
362
|
+
// Hydrate template with variables
|
|
363
|
+
const hydrateResult = hydrateTemplate(parsedTemplate, {
|
|
364
|
+
domain: 'n8n.example.com',
|
|
365
|
+
fallbackPort: port,
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
const config: TemplateProps = {
|
|
369
|
+
env: { account: '123456789012', region: 'us-east-1' },
|
|
370
|
+
application: 'myapp',
|
|
371
|
+
service: 'n8n',
|
|
372
|
+
environment: 'prod',
|
|
373
|
+
|
|
374
|
+
templateSlug: 'n8n',
|
|
375
|
+
instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO),
|
|
376
|
+
authorizedKeys: ['ssh-rsa AAAAB3... user@example.com'],
|
|
377
|
+
hydrateResult,
|
|
378
|
+
|
|
379
|
+
// Optional: Custom domain with SSL
|
|
380
|
+
domain: 'n8n.example.com',
|
|
381
|
+
hostedZoneId: 'Z123456789',
|
|
382
|
+
acmeEmail: 'admin@example.com',
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
new Template(new Cdk.App(), 'myapp-n8n-prod-stack', config);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
main();
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Available Templates:** See the [Coolify templates repository](https://github.com/coollabsio/coolify/tree/v4.x/templates/compose) for available templates.
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## CLI Commands
|
|
396
|
+
|
|
397
|
+
| Command | Description |
|
|
398
|
+
| :--- | :--- |
|
|
399
|
+
| `th init` | Scaffold a new project or service |
|
|
400
|
+
| `th deploy` | Deploy stacks to AWS |
|
|
401
|
+
| `th destroy` | Remove resources from AWS |
|
|
402
|
+
|
|
403
|
+
## Documentation
|
|
404
|
+
|
|
405
|
+
For detailed documentation on each construct and advanced configurations, see the [Wiki](https://github.com/thunder-so/thunder/wiki).
|
|
406
|
+
|
|
407
|
+
## License
|
|
408
|
+
|
|
409
|
+
Apache-2.0
|