Claude-skill-registry domain-management
Configure domain routing and Cloudflare DNS for sgcarstrends.com and subdomains. Use when adding new services, updating domain patterns, or debugging DNS issues.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/domain-management" ~/.claude/skills/majiayu000-claude-skill-registry-domain-management && rm -rf "$T"
skills/data/domain-management/SKILL.mdDomain Management Skill
This skill helps you manage domains and DNS configuration for the SG Cars Trends platform.
When to Use This Skill
- Adding new subdomains
- Configuring SSL certificates
- Updating DNS records
- Debugging domain resolution issues
- Setting up custom domains for services
- Managing Cloudflare settings
- Troubleshooting SSL/TLS errors
Domain Architecture
Domain Structure
sgcarstrends.com # Production web app staging.sgcarstrends.com # Staging web app dev.sgcarstrends.com # Development web app api.sgcarstrends.com # Production API api.staging.sgcarstrends.com # Staging API api.dev.sgcarstrends.com # Development API docs.sgcarstrends.com # Documentation (future)
Naming Convention
Web Apps:
- Production: Apex domain (
)sgcarstrends.com - Other envs:
{stage}.sgcarstrends.com
Backend Services:
- Pattern:
{service}.{stage}.sgcarstrends.com - Production service:
(no stage prefix){service}.sgcarstrends.com
Examples:
api.sgcarstrends.com # Production API api.staging.sgcarstrends.com # Staging API websocket.sgcarstrends.com # Production WebSocket service websocket.dev.sgcarstrends.com # Dev WebSocket service
DNS Provider: Cloudflare
Why Cloudflare?
- Free SSL certificates
- DDoS protection
- CDN capabilities
- Fast DNS propagation
- Analytics and logs
- Page Rules for optimization
DNS Management
Cloudflare manages DNS records, AWS Route53 is for SSL certificate validation only.
SST Domain Configuration
DNS Stack
// infra/dns.ts import { StackContext } from "sst/constructs"; import * as route53 from "aws-cdk-lib/aws-route53"; export function DNS({ stack }: StackContext) { // Import existing hosted zone (created in Route53) const hostedZone = route53.HostedZone.fromLookup(stack, "HostedZone", { domainName: "sgcarstrends.com", }); stack.addOutputs({ HostedZoneId: hostedZone.hostedZoneId, HostedZoneName: hostedZone.zoneName, }); return { hostedZone }; }
Web App Domain
// infra/web.ts import { StackContext, NextjsSite, use } from "sst/constructs"; import { DNS } from "./dns"; export function Web({ stack, app }: StackContext) { const { hostedZone } = use(DNS); const web = new NextjsSite(stack, "web", { path: "apps/web", customDomain: { domainName: app.stage === "production" ? "sgcarstrends.com" // Apex domain for prod : `${app.stage}.sgcarstrends.com`, // Subdomain for others hostedZone: hostedZone.zoneName, }, }); stack.addOutputs({ WebUrl: web.url, WebDomain: web.customDomainUrl, }); return { web }; }
API Domain
// infra/api.ts import { StackContext, Function, use } from "sst/constructs"; import { DNS } from "./dns"; export function API({ stack, app }: StackContext) { const { hostedZone } = use(DNS); const api = new Function(stack, "api", { handler: "apps/api/src/index.handler", url: { domain: { domainName: app.stage === "production" ? "api.sgcarstrends.com" : `api.${app.stage}.sgcarstrends.com`, hostedZone: hostedZone.zoneName, }, }, }); stack.addOutputs({ ApiUrl: api.url, ApiDomain: api.url, }); return { api }; }
Cloudflare Configuration
DNS Records
Cloudflare DNS records point to AWS CloudFront or Lambda Function URLs:
Type Name Value Proxy CNAME sgcarstrends.com d111111abcdef8.cloudfront.net ✓ Proxied CNAME staging d222222abcdef8.cloudfront.net ✓ Proxied CNAME dev d333333abcdef8.cloudfront.net ✓ Proxied CNAME api abc123.lambda-url.ap-southeast-1.on.aws ✓ Proxied CNAME api.staging def456.lambda-url.ap-southeast-1.on.aws ✓ Proxied
SSL/TLS Settings
Encryption Mode: Full (strict)
- Encrypts traffic from browser to Cloudflare
- Encrypts traffic from Cloudflare to origin (AWS)
- Validates origin certificate
Edge Certificates:
- Automatically provisioned by Cloudflare
- Covers
and*.sgcarstrends.comsgcarstrends.com - Auto-renewed
Page Rules
Rule 1: Cache API responses URL: api.sgcarstrends.com/* Settings: - Cache Level: Standard - Edge Cache TTL: 1 hour Rule 2: Always use HTTPS URL: *sgcarstrends.com/* Settings: - Always Use HTTPS: On Rule 3: Security headers URL: sgcarstrends.com/* Settings: - Security Headers: On - HSTS: Enabled
SSL Certificate Management
AWS Certificate Manager
SST automatically requests certificates from ACM:
// Automatic when using customDomain const web = new NextjsSite(stack, "web", { customDomain: { domainName: "sgcarstrends.com", hostedZone: hostedZone.zoneName, }, }); // SST will: // 1. Request certificate from ACM // 2. Add DNS validation records to Route53 // 3. Wait for validation // 4. Attach certificate to CloudFront/Lambda
Manual Certificate Request
If needed:
# Request certificate aws acm request-certificate \ --domain-name sgcarstrends.com \ --subject-alternative-names *.sgcarstrends.com \ --validation-method DNS \ --region us-east-1 # CloudFront requires us-east-1 # Get validation records aws acm describe-certificate \ --certificate-arn arn:aws:acm:... \ --region us-east-1
Add validation CNAME records to Cloudflare DNS.
Adding New Subdomains
1. Define in SST
// infra/new-service.ts import { StackContext, Function, use } from "sst/constructs"; import { DNS } from "./dns"; export function NewService({ stack, app }: StackContext) { const { hostedZone } = use(DNS); const service = new Function(stack, "new-service", { handler: "apps/new-service/src/index.handler", url: { domain: { domainName: app.stage === "production" ? "newservice.sgcarstrends.com" : `newservice.${app.stage}.sgcarstrends.com`, hostedZone: hostedZone.zoneName, }, }, }); return { service }; }
2. Deploy
npx sst deploy --stage production
SST will:
- Request ACM certificate
- Create Route53 records for validation
- Wait for validation
- Create Lambda Function URL or CloudFront distribution
- Output the AWS resource URL
3. Add Cloudflare DNS
Get the AWS URL from SST outputs, then:
- Go to Cloudflare dashboard
- Select
domainsgcarstrends.com - Click "DNS" → "Add record"
- Type: CNAME
- Name:
(ornewservice
)newservice.staging - Target: The AWS URL (CloudFront or Lambda)
- Proxy status: Proxied (orange cloud)
- TTL: Auto
- Save
4. Verify
# Check DNS resolution dig newservice.sgcarstrends.com # Test HTTPS curl -I https://newservice.sgcarstrends.com
Debugging DNS Issues
Check DNS Propagation
# Check Cloudflare DNS dig @1.1.1.1 sgcarstrends.com dig @1.1.1.1 api.sgcarstrends.com # Check global propagation dig sgcarstrends.com @8.8.8.8 # Google DNS dig sgcarstrends.com @1.1.1.1 # Cloudflare DNS # Or use online tools # https://www.whatsmydns.net/#CNAME/api.sgcarstrends.com
Check SSL Certificate
# Check certificate details openssl s_client -connect sgcarstrends.com:443 -servername sgcarstrends.com # Check certificate expiry echo | openssl s_client -connect sgcarstrends.com:443 -servername sgcarstrends.com 2>/dev/null | openssl x509 -noout -dates
Test Domain Resolution
# Test HTTP → HTTPS redirect curl -I http://sgcarstrends.com # Test HTTPS curl -I https://sgcarstrends.com # Test API endpoint curl -I https://api.sgcarstrends.com/health
Common Issues
Issue: DNS not resolving Solutions:
- Check Cloudflare DNS record exists
- Verify record type (CNAME vs A)
- Check proxy status (should be Proxied)
- Wait for propagation (usually < 5 minutes)
Issue: SSL certificate error Solutions:
- Check Cloudflare SSL mode is "Full (strict)"
- Verify ACM certificate is issued
- Check certificate covers the subdomain
- Verify Route53 has validation records
Issue: 522 error (Connection timed out) Solutions:
- Check Lambda/CloudFront is running
- Verify security groups allow HTTPS
- Check origin server is responding
- Review Cloudflare → Origin connection
Issue: Redirecting to wrong domain Solutions:
- Check SST
configurationcustomDomain - Verify Cloudflare page rules
- Check application redirect logic
CORS Configuration
When API and Web are on different domains:
// apps/api/src/index.ts import { Hono } from "hono"; import { cors } from "hono/cors"; const app = new Hono(); app.use("/*", cors({ origin: [ "https://sgcarstrends.com", "https://staging.sgcarstrends.com", "https://dev.sgcarstrends.com", "http://localhost:3001", // Local development ], credentials: true, }));
Monitoring
Cloudflare Analytics
- Go to Cloudflare dashboard
- Select domain
- Click "Analytics & Logs"
View:
- Traffic stats
- Performance metrics
- Security events
- Cache analytics
AWS Route53 Health Checks
// infra/monitoring.ts import { StackContext } from "sst/constructs"; import * as route53 from "aws-cdk-lib/aws-route53"; export function Monitoring({ stack }: StackContext) { new route53.CfnHealthCheck(stack, "ApiHealthCheck", { healthCheckConfig: { type: "HTTPS", fullyQualifiedDomainName: "api.sgcarstrends.com", port: 443, resourcePath: "/health", requestInterval: 30, failureThreshold: 3, }, }); }
Domain Migration
Migrating to New Domain
- Set up new domain in Cloudflare
- Deploy to new domain:
customDomain: { domainName: "new-domain.com", hostedZone: newHostedZone.zoneName, } - Test new domain thoroughly
- Set up redirects from old to new:
// Cloudflare page rule URL: old-domain.com/* Forwarding URL: 301 - https://new-domain.com/$1 - Update all references
- Monitor traffic
- Keep old domain for 6-12 months
Apex Domain Considerations
Using Apex Domain
The project uses apex domain (
sgcarstrends.com) for production:
Advantages:
- Shorter, cleaner URL
- Better for branding
- SEO benefits
Challenges:
- CNAME at apex not allowed by DNS spec
- Solution: Cloudflare CNAME flattening
Cloudflare CNAME Flattening
Cloudflare automatically flattens CNAMEs at apex:
# This works with Cloudflare: CNAME sgcarstrends.com → d111111abcdef8.cloudfront.net # Cloudflare resolves it to: A sgcarstrends.com → 104.21.x.x A sgcarstrends.com → 172.67.x.x
Subdomain Strategy
Current Subdomains
Web apps: sgcarstrends.com # Production staging.sgcarstrends.com # Staging dev.sgcarstrends.com # Development API: api.sgcarstrends.com # Production api.staging... # Staging api.dev... # Development Future: docs.sgcarstrends.com # Documentation status.sgcarstrends.com # Status page
Adding Future Services
Follow the pattern:
- Production:
{service}.sgcarstrends.com - Non-production:
{service}.{stage}.sgcarstrends.com
Security Headers
Configure in Cloudflare or application:
// apps/web/next.config.js const securityHeaders = [ { key: "X-DNS-Prefetch-Control", value: "on", }, { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload", }, { key: "X-Frame-Options", value: "SAMEORIGIN", }, { key: "X-Content-Type-Options", value: "nosniff", }, { key: "Referrer-Policy", value: "origin-when-cross-origin", }, ]; const nextConfig = { async headers() { return [ { source: "/:path*", headers: securityHeaders, }, ]; }, };
References
- Cloudflare Docs: https://developers.cloudflare.com
- AWS Route53: https://docs.aws.amazon.com/route53
- SST Custom Domains: https://docs.sst.dev/custom-domains
- Related files:
- DNS configurationinfra/dns.ts
- Infrastructure documentationinfra/CLAUDE.md
Best Practices
- Use Cloudflare Proxy: Enable orange cloud for DDoS protection
- Full (Strict) SSL: Always use strict SSL mode
- HTTPS Only: Enforce HTTPS with page rules
- Consistent Naming: Follow
pattern{service}.{stage}.domain - Certificate Management: Let SST handle ACM certificates
- DNS TTL: Use Auto for active development, higher for stable
- Monitoring: Set up health checks for critical domains
- Documentation: Document all subdomains and their purpose