import alchemy from "alchemy";
import AWS from "alchemy/aws/control";
import { AccountId } from "alchemy/aws";
const domainName = "onlybible.app";
const appName = 'onlybible';
const app = await alchemy("");
{ Key: "App", Value: appName },
{ Key: "Stage", Value: app.stage },
{ Key: "ProvisionedBy", Value: "Alchemy" }
const Comment = `ProvisionedBy Alchemy - ${appName} - ${app.stage}`;
const hostedZone = await AWS.Route53.HostedZone(`hosted-zone-${app.stage}`, {
// S3 Buckets with Public Access Block Configuration
const websiteBucket = await AWS.S3.Bucket(`website-bucket-${app.stage}`, {
BucketName: `${appName}-website-${app.stage}`,
PublicAccessBlockConfiguration: {
RestrictPublicBuckets: true
// CloudFront Origin Access Control
const s3OAC = await AWS.CloudFront.OriginAccessControl(`s3-oac-${app.stage}`, {
OriginAccessControlConfig: {
Name: `${appName}-s3-oac-${app.stage}`,
OriginAccessControlOriginType: "s3",
SigningBehavior: "always",
SigningProtocol: "sigv4",
const htmlRedirector = await AWS.CloudFront.Function(`html-redirector-${app.stage}`, {
Name: `${appName}_html_redirector_${app.stage}`,
Comment: "HTML redirector function",
Runtime: "cloudfront-js-2.0"
FunctionCode: `function handler(event) {
const request = event.request;
request.uri += 'index.html';
} else if (!uri.startsWith('/_astro')) {
request.uri += '/index.html';
const websiteDistribution = await AWS.CloudFront.Distribution(`s3-distribution-${app.stage}`, {
DomainName: websiteBucket.RegionalDomainName,
Id: websiteBucket.RegionalDomainName,
OriginAccessControlId: s3OAC.Id,
DefaultRootObject: "index.html",
CustomErrorResponses: [400, 403, 404, 405, 414, 416, 500, 501, 502, 503, 504].map(code => ({
ResponsePagePath: code < 500 ? "/404.html" : "/500.html"
AllowedMethods: ["GET", "HEAD"],
CachedMethods: ["GET", "HEAD"],
TargetOriginId: websiteBucket.RegionalDomainName,
ViewerProtocolPolicy: "redirect-to-https",
EventType: "viewer-request",
FunctionARN: htmlRedirector.FunctionARN
AllowedMethods: ["GET", "HEAD"],
CachedMethods: ["GET", "HEAD"],
TargetOriginId: websiteBucket.RegionalDomainName,
ViewerProtocolPolicy: "redirect-to-https",
EventType: "viewer-request",
FunctionARN: htmlRedirector.FunctionARN
PriceClass: "PriceClass_All",
SslSupportMethod: "sni-only",
AcmCertificateArn: "arn:aws:acm:us-east-1:122129753516:certificate/f8329274-9402-4f91-a8df-3e648567600d",
await AWS.S3.BucketPolicy(`website-bucket-policy-${app.stage}`, {
Bucket: websiteBucket.BucketName!,
Service: "cloudfront.amazonaws.com"
"AWS:SourceArn": `arn:aws:cloudfront::${await AccountId()}:distribution/${websiteDistribution.Id}`
// const aRecordDomain = await AWS.Route53.RecordSet("a-record-domain", {
// HostedZoneId: hostedZone.Id,
// DNSName: websiteDistribution.DomainName,
// HostedZoneId: websiteDistribution.DomainName, // CloudFront hosted zone ID
// EvaluateTargetHealth: false
// await $`bun run build`
// await $`aws s3 sync --delete ./dist/ s3://${websiteBucket.BucketName}`
// await $`aws cloudfront create-invalidation --distribution-id ${websiteDistribution.Id} --paths "/*" --no-cli-pager`