Compare commits
2 commits
34368e1dde
...
a57cdb029a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a57cdb029a | ||
|
|
f1bcc957f9 |
5 changed files with 37 additions and 166 deletions
|
|
@ -38,9 +38,6 @@ export default async function handler(req: any, res: any) {
|
|||
client_secret: clientSecret,
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
redirect_uri:
|
||||
process.env.DISCORD_ACTIVITY_REDIRECT_URI ||
|
||||
"https://aethex.dev/activity",
|
||||
}).toString(),
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -68,9 +68,22 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-purple-400",
|
||||
href: "/staff",
|
||||
},
|
||||
{
|
||||
id: "studio",
|
||||
name: "AeThex | Studio",
|
||||
label: "Studio",
|
||||
color: "#00ffff",
|
||||
bgColor: "bg-cyan-500/20",
|
||||
textColor: "text-cyan-400",
|
||||
href: "https://aethex.studio",
|
||||
external: true,
|
||||
},
|
||||
];
|
||||
|
||||
const STUDIO_SVG = `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="96" fill="%23050505"/><polygon points="256,48 444,152 444,360 256,464 68,360 68,152" fill="none" stroke="%2300ffff" stroke-width="18" opacity="0.9"/><text x="256" y="320" text-anchor="middle" font-family="Orbitron,monospace" font-size="220" font-weight="700" fill="%2300ffff">Æ</text></svg>')}`;
|
||||
|
||||
const LOGO_URLS: Record<string, string> = {
|
||||
studio: STUDIO_SVG,
|
||||
staff:
|
||||
"https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fc0414efd7af54ef4b821a05d469150d0?format=webp&width=800",
|
||||
labs: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fd93f7113d34347469e74421c3a3412e5?format=webp&width=800",
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ import blogIndexHandler from "../api/blog/index";
|
|||
import blogSlugHandler from "../api/blog/[slug]";
|
||||
import aiChatHandler from "../api/ai/chat";
|
||||
import aiTitleHandler from "../api/ai/title";
|
||||
import createCheckoutHandler from "../api/subscriptions/create-checkout";
|
||||
import manageSubscriptionHandler from "../api/subscriptions/manage";
|
||||
|
||||
// Developer API Keys handlers
|
||||
import {
|
||||
|
|
@ -340,6 +342,11 @@ export function createServer() {
|
|||
app.use((req, res, next) => {
|
||||
// Allow embedding in iframes (Discord Activities need this)
|
||||
res.setHeader("X-Frame-Options", "ALLOWALL");
|
||||
// CSP with frame-ancestors for Discord Activity embedding
|
||||
res.setHeader(
|
||||
"Content-Security-Policy",
|
||||
"default-src 'self' https: data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: blob: https:; font-src 'self' data: https:; connect-src 'self' https: wss:; frame-ancestors 'self' https://discord.com https://*.discord.com https://*.discordsays.com",
|
||||
);
|
||||
// Allow Discord to access the iframe
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
res.setHeader(
|
||||
|
|
@ -1815,9 +1822,6 @@ export function createServer() {
|
|||
client_secret: clientSecret,
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
redirect_uri:
|
||||
process.env.DISCORD_ACTIVITY_REDIRECT_URI ||
|
||||
"https://aethex.dev/activity",
|
||||
}).toString(),
|
||||
},
|
||||
);
|
||||
|
|
@ -8177,5 +8181,16 @@ export function createServer() {
|
|||
app.post("/api/ai/chat", aiChatHandler);
|
||||
app.post("/api/ai/title", aiTitleHandler);
|
||||
|
||||
// Subscription API routes
|
||||
app.post("/api/subscriptions/create-checkout", (req: express.Request, res: express.Response) => {
|
||||
return createCheckoutHandler(req as any, res as any);
|
||||
});
|
||||
app.get("/api/subscriptions/manage", (req: express.Request, res: express.Response) => {
|
||||
return manageSubscriptionHandler(req as any, res as any);
|
||||
});
|
||||
app.post("/api/subscriptions/manage", (req: express.Request, res: express.Response) => {
|
||||
return manageSubscriptionHandler(req as any, res as any);
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,6 +335,12 @@ app.get("*", async (req, res) => {
|
|||
return res.status(404).json({ error: "API endpoint not found" });
|
||||
}
|
||||
|
||||
// Don't serve the SPA shell for missing static-asset requests — they should 404
|
||||
// cleanly rather than returning HTML (which causes "Unexpected token '<'" JS errors).
|
||||
if (/\.(js|mjs|cjs|css|map|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|webp|avif)$/i.test(req.path)) {
|
||||
return res.status(404).send("Not found");
|
||||
}
|
||||
|
||||
try {
|
||||
const template = getTemplate();
|
||||
const meta = await resolveRouteMeta(req.path);
|
||||
|
|
|
|||
160
vercel.json
160
vercel.json
|
|
@ -1,160 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"buildCommand": "npm run build",
|
||||
"outputDirectory": "dist/spa",
|
||||
"functions": {
|
||||
"api/**/*.ts": {
|
||||
"memory": 1024,
|
||||
"maxDuration": 30
|
||||
}
|
||||
},
|
||||
"redirects": [
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "aethex.app" }],
|
||||
"destination": "https://aethex.dev/:path",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "aethex.locker" }],
|
||||
"destination": "https://aethex.dev/:path",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "aethex.studio" }],
|
||||
"destination": "https://aethex.dev/ethos/:path",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "aethex.info" }],
|
||||
"destination": "https://aethex.dev/foundation/:path",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "aethex.site" }],
|
||||
"destination": "https://aethex.dev/:path",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/",
|
||||
"has": [{ "type": "host", "value": "aethex.me" }],
|
||||
"destination": "https://aethex.dev/",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/",
|
||||
"has": [{ "type": "host", "value": "aethex.space" }],
|
||||
"destination": "https://aethex.dev/",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/feed",
|
||||
"destination": "/community/feed",
|
||||
"permanent": true
|
||||
}
|
||||
],
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "(?<proxy>.+)\\.discordsays\\.com" }],
|
||||
"destination": "/index.html"
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "(?<sub>.+)\\.aethex\\.me" }],
|
||||
"destination": "/index.html"
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "(?<sub>.+)\\.aethex\\.space" }],
|
||||
"destination": "/index.html"
|
||||
},
|
||||
{
|
||||
"source": "/api/:path(.*)",
|
||||
"destination": "/api/:path"
|
||||
},
|
||||
{ "source": "/", "destination": "/index.html" },
|
||||
{ "source": "/login", "destination": "/index.html" },
|
||||
{ "source": "/login/:path*", "destination": "/index.html" },
|
||||
{ "source": "/dashboard", "destination": "/index.html" },
|
||||
{ "source": "/dashboard/:path*", "destination": "/index.html" },
|
||||
{ "source": "/profile", "destination": "/index.html" },
|
||||
{ "source": "/profile/:path*", "destination": "/index.html" },
|
||||
{ "source": "/activity", "destination": "/index.html" },
|
||||
{ "source": "/activity/", "destination": "/index.html" },
|
||||
{ "source": "/activity/:path*", "destination": "/index.html" },
|
||||
{ "source": "/admin", "destination": "/index.html" },
|
||||
{ "source": "/admin/:path*", "destination": "/index.html" },
|
||||
{ "source": "/creators", "destination": "/index.html" },
|
||||
{ "source": "/creators/:path*", "destination": "/index.html" },
|
||||
{ "source": "/opportunities", "destination": "/index.html" },
|
||||
{ "source": "/opportunities/:path*", "destination": "/index.html" },
|
||||
{ "source": "/nexus", "destination": "/index.html" },
|
||||
{ "source": "/nexus/:path*", "destination": "/index.html" },
|
||||
{ "source": "/foundation", "destination": "/index.html" },
|
||||
{ "source": "/foundation/:path*", "destination": "/index.html" },
|
||||
{ "source": "/gameforge", "destination": "/index.html" },
|
||||
{ "source": "/gameforge/:path*", "destination": "/index.html" },
|
||||
{ "source": "/labs", "destination": "/index.html" },
|
||||
{ "source": "/labs/:path*", "destination": "/index.html" },
|
||||
{ "source": "/corp", "destination": "/index.html" },
|
||||
{ "source": "/corp/:path*", "destination": "/index.html" },
|
||||
{ "source": "/devlink", "destination": "/index.html" },
|
||||
{ "source": "/devlink/:path*", "destination": "/index.html" },
|
||||
{ "source": "/community", "destination": "/index.html" },
|
||||
{ "source": "/community/:path*", "destination": "/index.html" },
|
||||
{ "source": "/developers", "destination": "/index.html" },
|
||||
{ "source": "/developers/:path*", "destination": "/index.html" },
|
||||
{ "source": "/discord-verify", "destination": "/index.html" },
|
||||
{ "source": "/discord-verify/:path*", "destination": "/index.html" },
|
||||
{ "source": "/ethos", "destination": "/index.html" },
|
||||
{ "source": "/ethos/:path*", "destination": "/index.html" },
|
||||
{ "source": "/:path*", "destination": "/index.html" }
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"source": "/assets/(.*)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "public, max-age=31536000, immutable"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/(.*).(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff2)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "public, max-age=31536000, immutable"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/api/(.*)",
|
||||
"headers": [{ "key": "Cache-Control", "value": "no-store" }]
|
||||
},
|
||||
{
|
||||
"source": "/(.*)",
|
||||
"headers": [
|
||||
{ "key": "X-Content-Type-Options", "value": "nosniff" },
|
||||
{
|
||||
"key": "Referrer-Policy",
|
||||
"value": "strict-origin-when-cross-origin"
|
||||
},
|
||||
{
|
||||
"key": "Permissions-Policy",
|
||||
"value": "geolocation=(), microphone=(), camera=()"
|
||||
},
|
||||
{
|
||||
"key": "Content-Security-Policy",
|
||||
"value": "default-src 'self' https: data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: blob: https:; font-src 'self' data: https:; connect-src 'self' https: wss:; frame-ancestors 'self' https://discord.com https://*.discord.com https://*.discordsays.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue