diff --git a/website/.gitignore b/website/.gitignore index 6276b4a..0e2d37e 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -141,5 +141,8 @@ vite.config.ts.timestamp-* # Astro .astro +# Cloudflare Wrangler +.wrangler + # Mac OS .DS_Store \ No newline at end of file diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 5ca3946..106618b 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -6,6 +6,8 @@ import mdx from "@astrojs/mdx"; import react from "@astrojs/react"; import rehypeExternalLinks from "./src/utils/rehype-external-links.ts"; import playformCompress from "@playform/compress"; +import markdownForAgents from "astro-markdown-for-agents"; +import { markdownForAgentsOptions } from "./markdown-for-agents.config.mjs"; const SITE_BASE_URL = process.env.SITE_BASE_URL || "https://www.quantus.com"; const DEFAULT_LOCALE = "en-US"; @@ -99,5 +101,6 @@ export default defineConfig({ mdx(), react(), playformCompress(), + markdownForAgents(markdownForAgentsOptions), ], }); diff --git a/website/bun.lock b/website/bun.lock index 781797a..bbf8c43 100644 --- a/website/bun.lock +++ b/website/bun.lock @@ -16,6 +16,7 @@ "@radix-ui/react-slot": "^1.2.3", "@tanstack/react-table": "^8.21.3", "astro": "6.0.7", + "astro-markdown-for-agents": "^0.1.1", "astro-seo": "^0.8.4", "chart.js": "^4.5.1", "chartjs-plugin-datalabels": "^2.2.0", @@ -302,6 +303,8 @@ "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], + "@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -860,6 +863,8 @@ "astro": ["astro@6.0.7", "", { "dependencies": { "@astrojs/compiler": "^3.0.0", "@astrojs/internal-helpers": "0.8.0", "@astrojs/markdown-remark": "7.0.1", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^1.1.1", "devalue": "^5.6.3", "diff": "^8.0.3", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.27.3", "flattie": "^1.1.1", "fontace": "~0.4.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.1.1", "magic-string": "^0.30.21", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.3", "rehype": "^13.0.2", "semver": "^7.7.4", "shiki": "^4.0.0", "smol-toml": "^1.6.0", "svgo": "^4.0.0", "tinyclip": "^0.1.6", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unist-util-visit": "^5.1.0", "unstorage": "^1.17.4", "vfile": "^6.0.3", "vite": "^7.3.1", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0" }, "bin": { "astro": "bin/astro.mjs" } }, "sha512-tCUrtQI+2Dk13xTM07JYrvk16T4ekWqSXh0/dVCunne816ZV+RCs1tomSoTHZi3DJdoaTnLJmkH+uxCC3b1KWw=="], + "astro-markdown-for-agents": ["astro-markdown-for-agents@0.1.1", "", { "dependencies": { "turndown": "^7.2.0" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-ZUYEb+NTa8Wr0zGYKVItfa4NbDaooW5hV05KXvwhTA2T/K4h5+akpvBOZgubvduLkIh95/anGKM7T5Nm07lu/Q=="], + "astro-seo": ["astro-seo@0.8.4", "", { "dependencies": { "@astrojs/check": "^0.5.4" } }, "sha512-Ou1vzQSXAxa0K8rtNtXNvSpYqOGEgMhh0immMxJeXmbVZac3UKCNWAoXWyOQDFYsZvBugCRSg0N1phBqPMVgCw=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -2078,6 +2083,8 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "turndown": ["turndown@7.2.4", "", { "dependencies": { "@mixmark-io/domino": "^2.2.0" } }, "sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ=="], + "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], "type-level-regexp": ["type-level-regexp@0.1.17", "", {}, "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg=="], diff --git a/website/functions/_middleware.js b/website/functions/_middleware.js new file mode 100644 index 0000000..cea4c05 --- /dev/null +++ b/website/functions/_middleware.js @@ -0,0 +1,68 @@ +import { + applyMarkdownHeaders, + ensureVaryAccept, + markdownAssetPath, + prefersMarkdown, +} from "astro-markdown-for-agents/runtime"; +import { + MARKDOWN_NEGOTIATION_BYPASS_HEADER, + isNegotiablePath, + resolvedMarkdownOptions, +} from "../markdown-for-agents.config.mjs"; + +/** + * Serve pre-built markdown from dist/_markdown-cache when clients negotiate + * Accept: text/markdown. HTML remains the default for browsers. + */ +export async function onRequest(context) { + const { request, env } = context; + const method = request.method.toUpperCase(); + + if (method !== "GET" && method !== "HEAD") { + return context.next(); + } + + if (request.headers.get(MARKDOWN_NEGOTIATION_BYPASS_HEADER) === "1") { + return context.next(); + } + + const accept = request.headers.get("Accept") ?? ""; + if (!prefersMarkdown(accept, resolvedMarkdownOptions.preferPlainText)) { + return context.next(); + } + + const pathname = new URL(request.url).pathname; + if (!isNegotiablePath(pathname, resolvedMarkdownOptions)) { + return context.next(); + } + + const mdPath = markdownAssetPath( + pathname, + resolvedMarkdownOptions.markdownDir, + ); + const mdRequest = new Request(new URL(mdPath, request.url), { + method, + headers: { + [MARKDOWN_NEGOTIATION_BYPASS_HEADER]: "1", + }, + }); + + const mdResponse = env.ASSETS + ? await env.ASSETS.fetch(mdRequest) + : await fetch(mdRequest); + + if (!mdResponse.ok) { + return context.next(); + } + + const markdown = await mdResponse.text(); + const headers = new Headers(mdResponse.headers); + applyMarkdownHeaders(headers, markdown, resolvedMarkdownOptions); + ensureVaryAccept(headers); + + if (method === "HEAD") { + return new Response(null, { status: mdResponse.status, headers }); + } + + return new Response(markdown, { status: mdResponse.status, headers }); +} diff --git a/website/markdown-for-agents.config.mjs b/website/markdown-for-agents.config.mjs new file mode 100644 index 0000000..c90346c --- /dev/null +++ b/website/markdown-for-agents.config.mjs @@ -0,0 +1,93 @@ +/** @type {import('astro-markdown-for-agents').MarkdownForAgentsOptions} */ +export const markdownForAgentsOptions = { + excludePrefixes: ["/api/", "/_astro/", "/.well-known/", "/_markdown-cache/"], + contentSignals: { + aiTrain: true, + search: true, + aiInput: true, + }, +}; + +/** Resolved options for edge middleware (runtime-safe, no Node imports). */ +export const resolvedMarkdownOptions = { + include: [], + exclude: [], + excludePrefixes: markdownForAgentsOptions.excludePrefixes ?? [], + excludeExtensions: [ + ".css", + ".js", + ".mjs", + ".map", + ".json", + ".xml", + ".txt", + ".ico", + ".png", + ".jpg", + ".jpeg", + ".webp", + ".svg", + ".gif", + ".pdf", + ".zip", + ".woff", + ".woff2", + ], + markdownDir: markdownForAgentsOptions.markdownDir ?? "_markdown-cache", + contentSignalHeader: "ai-train=yes, search=yes, ai-input=yes", + maxExtractedChars: Infinity, + preferPlainText: markdownForAgentsOptions.preferPlainText ?? true, +}; + +export const MARKDOWN_NEGOTIATION_BYPASS_HEADER = + "x-markdown-negotiation-bypass"; + +function extensionOf(value) { + const dotIndex = value.lastIndexOf("."); + if (dotIndex === -1) { + return ""; + } + return value.slice(dotIndex).toLowerCase(); +} + +function matches(pathname, matcher) { + if (typeof matcher === "function") { + return matcher(pathname); + } + if (matcher instanceof RegExp) { + return matcher.test(pathname); + } + if (!matcher.includes("*")) { + return pathname === matcher; + } + const regex = new RegExp( + `^${matcher.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, + ); + return regex.test(pathname); +} + +function matchesAny(pathname, matchers) { + return matchers.some((matcher) => matches(pathname, matcher)); +} + +/** Edge-safe mirror of astro-markdown-for-agents route matching. */ +export function isNegotiablePath(pathname, options) { + if (!pathname) { + return false; + } + if (matchesAny(pathname, options.exclude)) { + return false; + } + if (options.include.length > 0 && !matchesAny(pathname, options.include)) { + return false; + } + if (options.excludePrefixes.some((prefix) => pathname.startsWith(prefix))) { + return false; + } + const lastSegment = pathname.split("/").pop() ?? ""; + const ext = extensionOf(lastSegment); + if (ext && options.excludeExtensions.includes(ext)) { + return false; + } + return !lastSegment.includes(".") || ext === ""; +} diff --git a/website/package.json b/website/package.json index eea7dcc..5a7abe7 100644 --- a/website/package.json +++ b/website/package.json @@ -24,6 +24,7 @@ "@radix-ui/react-slot": "^1.2.3", "@tanstack/react-table": "^8.21.3", "astro": "6.0.7", + "astro-markdown-for-agents": "^0.1.1", "astro-seo": "^0.8.4", "chart.js": "^4.5.1", "chartjs-plugin-datalabels": "^2.2.0", diff --git a/website/public/.well-known/api-catalog b/website/public/.well-known/api-catalog new file mode 100644 index 0000000..f46af40 --- /dev/null +++ b/website/public/.well-known/api-catalog @@ -0,0 +1,67 @@ +{ + "linkset": [ + { + "anchor": "https://api.quantus.com/api", + "service-desc": [ + { + "href": "https://www.quantus.com/.well-known/openapi/website-api.json", + "type": "application/json" + } + ], + "service-doc": [ + { + "href": "https://docs.quantus.com/", + "type": "text/html" + } + ], + "status": [ + { + "href": "https://api.quantus.com/", + "type": "text/plain" + } + ] + }, + { + "anchor": "https://quests.quantus.com/api", + "service-desc": [ + { + "href": "https://www.quantus.com/.well-known/openapi/quests-api.json", + "type": "application/json" + } + ], + "service-doc": [ + { + "href": "https://docs.quantus.com/", + "type": "text/html" + } + ], + "status": [ + { + "href": "https://quests.quantus.com/health", + "type": "application/json" + } + ] + }, + { + "anchor": "https://sub2.quantus.com/v1/graphql", + "service-desc": [ + { + "href": "https://www.quantus.com/.well-known/openapi/indexer-api.json", + "type": "application/json" + } + ], + "service-doc": [ + { + "href": "https://docs.quantus.com/", + "type": "text/html" + } + ], + "status": [ + { + "href": "https://sub2.quantus.com/health", + "type": "application/json" + } + ] + } + ] +} diff --git a/website/public/.well-known/openapi/indexer-api.json b/website/public/.well-known/openapi/indexer-api.json new file mode 100644 index 0000000..dff2210 --- /dev/null +++ b/website/public/.well-known/openapi/indexer-api.json @@ -0,0 +1,58 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Quantus Indexer GraphQL API", + "version": "1.0.0", + "description": "GraphQL indexer for Quantus chain statistics and on-chain data." + }, + "servers": [{ "url": "https://sub2.quantus.com" }], + "paths": { + "/health": { + "get": { + "summary": "Service health", + "operationId": "getHealth", + "responses": { + "200": { + "description": "Indexer is healthy", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + } + } + }, + "/v1/graphql": { + "post": { + "summary": "GraphQL query endpoint", + "operationId": "graphqlQuery", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["query"], + "properties": { + "query": { "type": "string" }, + "variables": { + "type": "object", + "additionalProperties": true + }, + "operationName": { "type": "string" } + } + } + } + } + }, + "responses": { + "200": { "description": "GraphQL response" } + } + } + } + } +} diff --git a/website/public/.well-known/openapi/quests-api.json b/website/public/.well-known/openapi/quests-api.json new file mode 100644 index 0000000..7b0a5bc --- /dev/null +++ b/website/public/.well-known/openapi/quests-api.json @@ -0,0 +1,54 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Quantus Quests API", + "version": "1.0.0", + "description": "Task Master API for quests, leaderboards, and Ethereum risk analysis." + }, + "servers": [{ "url": "https://quests.quantus.com" }], + "paths": { + "/health": { + "get": { + "summary": "Service health", + "operationId": "getHealth", + "responses": { + "200": { + "description": "Service is healthy", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "healthy": { "type": "boolean" }, + "service": { "type": "string" }, + "version": { "type": "string" }, + "timestamp": { "type": "string", "format": "date-time" } + } + } + } + } + } + } + } + }, + "/api/risk-checker/{addressOrEnsName}": { + "get": { + "summary": "Get Ethereum quantum risk analysis", + "operationId": "getRiskAnalysis", + "parameters": [ + { + "name": "addressOrEnsName", + "in": "path", + "required": true, + "schema": { "type": "string" }, + "description": "Ethereum address or ENS name" + } + ], + "responses": { + "200": { "description": "Risk analysis result" }, + "400": { "description": "Invalid address or ENS name" } + } + } + } + } +} diff --git a/website/public/.well-known/openapi/website-api.json b/website/public/.well-known/openapi/website-api.json new file mode 100644 index 0000000..5532645 --- /dev/null +++ b/website/public/.well-known/openapi/website-api.json @@ -0,0 +1,110 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Quantus Website API", + "version": "1.0.0", + "description": "Public endpoints for contact inquiries, waitlist subscriptions, and sponsorship requests." + }, + "servers": [{ "url": "https://api.quantus.com" }], + "paths": { + "/": { + "get": { + "summary": "Service health", + "operationId": "getHealth", + "responses": { + "200": { + "description": "API is running" + } + } + } + }, + "/api/inquiries": { + "post": { + "summary": "Submit a contact inquiry", + "operationId": "createInquiry", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["name", "email", "message"], + "properties": { + "name": { "type": "string" }, + "email": { "type": "string", "format": "email" }, + "message": { "type": "string" } + } + } + } + } + }, + "responses": { + "200": { "description": "Inquiry sent successfully" }, + "400": { "description": "Validation error" } + } + } + }, + "/api/waitlist": { + "post": { + "summary": "Subscribe to the waitlist", + "operationId": "joinWaitlist", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["email", "firstName"], + "properties": { + "email": { "type": "string", "format": "email" }, + "firstName": { "type": "string" }, + "lastName": { "type": "string" } + } + } + } + } + }, + "responses": { + "201": { "description": "Added to waitlist" }, + "409": { "description": "Duplicate entry" } + } + } + }, + "/api/sponsorships": { + "post": { + "summary": "Submit a sponsorship request", + "operationId": "createSponsorship", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "email", + "designation", + "organization", + "investmentTier" + ], + "properties": { + "name": { "type": "string" }, + "email": { "type": "string", "format": "email" }, + "phone": { "type": "string" }, + "designation": { "type": "string" }, + "organization": { "type": "string" }, + "investmentTier": { "type": "string" }, + "additionalInfo": { "type": "string" } + } + } + } + } + }, + "responses": { + "200": { "description": "Sponsorship request sent" }, + "400": { "description": "Validation error" } + } + } + } + } +} diff --git a/website/public/_headers b/website/public/_headers index 79582f9..8311147 100644 --- a/website/public/_headers +++ b/website/public/_headers @@ -1,6 +1,44 @@ -/.well-known/* +/.well-known/api-catalog + Content-Type: application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727" + +/.well-known/openapi/* + Content-Type: application/json + +/.well-known/assetlinks.json Content-Type: application/json +/.well-known/apple-app-site-association + Content-Type: application/json + +# Agent discovery Link headers (RFC 8288 / RFC 9727) +/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/zh-CN/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/ko-KR/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/id-ID/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/ja-JP/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/ru-RU/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/es-ES/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/de-DE/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept +/hi-IN/ + Link: ; rel="api-catalog", ; rel="service-doc" + Vary: Accept + # Cache static assets with long cache lifetimes # Font files - cache for 1 year (immutable) /_astro/*.woff2 @@ -64,6 +102,11 @@ /_astro/* Cache-Control: public, max-age=31536000, immutable -# HTML files - no cache +# HTML files - no cache; vary by Accept for markdown negotiation /*.html - Cache-Control: no-cache \ No newline at end of file + Cache-Control: no-cache + Vary: Accept + +/_markdown-cache/* + Cache-Control: no-cache + X-Robots-Tag: noindex \ No newline at end of file diff --git a/website/src/api/node-rpc-service.ts b/website/src/api/node-rpc-service.ts index 7531043..ddc11b5 100644 --- a/website/src/api/node-rpc-service.ts +++ b/website/src/api/node-rpc-service.ts @@ -261,7 +261,9 @@ class NodeRpcService { } } - private deserializeFeed(data: string): Array<{ action: number; payload: unknown }> { + private deserializeFeed( + data: string, + ): Array<{ action: number; payload: unknown }> { const json = JSON.parse(data) as unknown; if (!Array.isArray(json) || json.length === 0 || json.length % 2 !== 0) { diff --git a/website/src/config/index.ts b/website/src/config/index.ts index 3e63a46..1ffc41b 100644 --- a/website/src/config/index.ts +++ b/website/src/config/index.ts @@ -8,7 +8,7 @@ const env = { API_URL: "https://api.quantus.com/api", TASK_MASTER_URL: "https://quests.quantus.com/api", // TASK_MASTER_URL: "http://localhost:3000/api", - GRAPHQL_URL: "https://subsquid.quantus.com/graphql", + GRAPHQL_URL: "https://sub2.quantus.com/v1/graphql", }; export default env; diff --git a/website/src/constants/default-metadata.ts b/website/src/constants/default-metadata.ts index cb48be9..ca068f1 100644 --- a/website/src/constants/default-metadata.ts +++ b/website/src/constants/default-metadata.ts @@ -8,12 +8,12 @@ const title = { const description = "Quantus: Quantum-secure Layer 1 blockchain. Download our wallet for post-quantum protected assets."; const image = { - url: `${env.SITE_BASE_URL}/banner-small.jpeg`, - secureUrl: `${env.SITE_BASE_URL}/banner-small.jpeg`, + url: `${env.SITE_BASE_URL}/quantus-banner.png`, + secureUrl: `${env.SITE_BASE_URL}/quantus-banner.png`, alt: "Banner with gradient text reading 'Quantum Secure Your Crypto' in pink, purple, and yellow tones on a dark background with abstract circular shapes.", - width: 600, - height: 200, - type: "image/jpeg", + width: 6000, + height: 3140, + type: "image/png", }; const defaultMetadata: SEOProps = { diff --git a/website/src/constants/footer-navigations.ts b/website/src/constants/footer-navigations.ts index b02bf59..8871c86 100644 --- a/website/src/constants/footer-navigations.ts +++ b/website/src/constants/footer-navigations.ts @@ -93,7 +93,7 @@ export const FOOTER_NAVIGATIONS: Navigation[] = [ href: "https://blockspot.io/coin/quantus/", target: "_blank", rel: "noopener noreferrer", - } + }, ], }, ] as const; diff --git a/website/src/constants/site-navigations.ts b/website/src/constants/site-navigations.ts index 507f373..ac5b35f 100644 --- a/website/src/constants/site-navigations.ts +++ b/website/src/constants/site-navigations.ts @@ -1,10 +1,8 @@ interface Navigation { - href: string; label: string; target?: string; rel?: string; - } export const SITE_NAVIGATIONS: Navigation[] = [ @@ -13,8 +11,10 @@ export const SITE_NAVIGATIONS: Navigation[] = [ { href: "/about/", label: "navbar.about" }, { href: "/community/", label: "navbar.community" }, { - href: "https://docs.quantus.com/", target: "_blank", - rel: "noopener noreferrer", label: "navbar.docs" + href: "https://docs.quantus.com/", + target: "_blank", + rel: "noopener noreferrer", + label: "navbar.docs", }, { href: "/quantum-risk-checker/", diff --git a/website/src/constants/teams.ts b/website/src/constants/teams.ts index e0d5e4a..e310302 100644 --- a/website/src/constants/teams.ts +++ b/website/src/constants/teams.ts @@ -1,62 +1,62 @@ export const TEAMS = [ - { - id: "christopher-smith", - name: "Christopher Smith", - role: "CEO", - social: { - platform: "X", - url: "https://x.com/YuviLightman", - username: "@YuviLightman", - } + { + id: "christopher-smith", + name: "Christopher Smith", + role: "CEO", + social: { + platform: "X", + url: "https://x.com/YuviLightman", + username: "@YuviLightman", }, - { - id: "joe-mattia", - name: "Joseph Mattia", - role: "COO", - social: { - platform: "X", - url: "https://x.com/JoeMattia", - username: "@JoeMattia", - } + }, + { + id: "joe-mattia", + name: "Joseph Mattia", + role: "COO", + social: { + platform: "X", + url: "https://x.com/JoeMattia", + username: "@JoeMattia", }, - { - id: "nikolaus-hager", - name: "Nikolaus Hager", - role: "CTO", - social: { - platform: "X", - url: "https://x.com/n13", - username: "@n13", - } + }, + { + id: "nikolaus-hager", + name: "Nikolaus Hager", + role: "CTO", + social: { + platform: "X", + url: "https://x.com/n13", + username: "@n13", }, - { - id: "jarrod-jay-frankel", - name: "Jarrod Frankel", - role: "CMO", - social: { - platform: "X", - url: "https://x.com/j_in_marketing", - username: "@j_in_marketing", - } + }, + { + id: "jarrod-jay-frankel", + name: "Jarrod Frankel", + role: "CMO", + social: { + platform: "X", + url: "https://x.com/j_in_marketing", + username: "@j_in_marketing", }, - { - id: "ethan-cemer", - name: "Ethan Cemer", - role: "Zero-Knowledge Engineer", - social: { - platform: "X", - url: "https://x.com/ethan_t_c_", - username: "@ethan_t_c_", - } + }, + { + id: "ethan-cemer", + name: "Ethan Cemer", + role: "Zero-Knowledge Engineer", + social: { + platform: "X", + url: "https://x.com/ethan_t_c_", + username: "@ethan_t_c_", }, - { - id: "jonathan-angle", - name: "Jonathan Angle", - role: "Communications Director", - social: { - platform: "X", - url: "https://x.com/defijangle", - username: "@defijangle", - } + }, + { + id: "jonathan-angle", + name: "Jonathan Angle", + role: "Communications Director", + social: { + platform: "X", + url: "https://x.com/defijangle", + username: "@defijangle", }, -] as const; \ No newline at end of file + }, +] as const; diff --git a/website/src/contents/blogs/de-DE/weekly-update-04-15-2026.md b/website/src/contents/blogs/de-DE/weekly-update-04-15-2026.md index b446cc5..a547f72 100644 --- a/website/src/contents/blogs/de-DE/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/de-DE/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Das haben wir diese Woche sonst noch ausgeliefert: ### Content & Partnerships - Chris im [@mobymedia](https://x.com/mobymedia)-Podcast: [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- Podcast zu Post-Quantum-Zero-Knowledge-Beweisen mit [@ethan_t_c_](https://x.com/ethan_t_c_) und [@YuviLightman](https://x.com/YuviLightman) veröffentlicht: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- Podcast zu Post-Quantum-Zero-Knowledge-Beweisen mit [@ethan*t_c*](https://x.com/ethan_t_c_) und [@YuviLightman](https://x.com/YuviLightman) veröffentlicht: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - GitEx in Singapur besucht. - Ausverkaufte Session mit Dr. [@zina_cinker](https://x.com/zina_cinker) an der Network School: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris bei [@ArcanumVentures](https://x.com/ArcanumVentures) Folge 47 live am Donnerstag, 16. April, 14:00 UTC / 22:00 Singapur: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/en-US/weekly-update-04-15-2026.md b/website/src/contents/blogs/en-US/weekly-update-04-15-2026.md index 9365b2b..c789289 100644 --- a/website/src/contents/blogs/en-US/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/en-US/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Here's what else we shipped this week: ### Content & Partnerships - Chris on [@mobymedia](https://x.com/mobymedia) podcast: [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- Published Post-Quantum zero-knowledge proofs podcast with [@ethan_t_c_](https://x.com/ethan_t_c_) and [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- Published Post-Quantum zero-knowledge proofs podcast with [@ethan*t_c*](https://x.com/ethan_t_c_) and [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - Attended GitEx in Singapore. - Hosted a full-house session with Dr. [@zina_cinker](https://x.com/zina_cinker) at Network School: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris joining [@ArcanumVentures](https://x.com/ArcanumVentures) ep. 47 live Thursday April 16, 2pm UTC / 10pm Singapore: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/es-ES/weekly-update-04-15-2026.md b/website/src/contents/blogs/es-ES/weekly-update-04-15-2026.md index 3013771..96d0251 100644 --- a/website/src/contents/blogs/es-ES/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/es-ES/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Esto es lo más que lanzamos esta semana: ### Content & Partnerships - Chris en el podcast de [@mobymedia](https://x.com/mobymedia): [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- Publicamos el podcast sobre pruebas de conocimiento cero post-cuánticas con [@ethan_t_c_](https://x.com/ethan_t_c_) y [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- Publicamos el podcast sobre pruebas de conocimiento cero post-cuánticas con [@ethan*t_c*](https://x.com/ethan_t_c_) y [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - Asistimos a GitEx en Singapur. - Organizamos una sesión a sala llena con la Dra. [@zina_cinker](https://x.com/zina_cinker) en Network School: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris se une a [@ArcanumVentures](https://x.com/ArcanumVentures) ep. 47 en directo el jueves 16 de abril, 14:00 UTC / 22:00 Singapur: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/hi-IN/weekly-update-04-15-2026.md b/website/src/contents/blogs/hi-IN/weekly-update-04-15-2026.md index e5f34f7..c19f02c 100644 --- a/website/src/contents/blogs/hi-IN/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/hi-IN/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Quantus प्रूफ ऑफ वर्क है। अधिकतम आप ### Content & Partnerships - Chris [@mobymedia](https://x.com/mobymedia) पॉडकास्ट पर: [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- [@ethan_t_c_](https://x.com/ethan_t_c_) और [@YuviLightman](https://x.com/YuviLightman) के साथ पोस्ट-क्वांटम ज़ीरो-नॉलेज प्रूफ़ पॉडकास्ट प्रकाशित: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- [@ethan*t_c*](https://x.com/ethan_t_c_) और [@YuviLightman](https://x.com/YuviLightman) के साथ पोस्ट-क्वांटम ज़ीरो-नॉलेज प्रूफ़ पॉडकास्ट प्रकाशित: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - सिंगापुर में GitEx में भाग लिया। - Dr. [@zina_cinker](https://x.com/zina_cinker) के साथ Network School पर फुल-हाउस सत्र: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris [@ArcanumVentures](https://x.com/ArcanumVentures) ep. 47 लाइव गुरुवार 16 अप्रैल, 14:00 UTC / 22:00 सिंगापुर: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/id-ID/weekly-update-04-15-2026.md b/website/src/contents/blogs/id-ID/weekly-update-04-15-2026.md index e8e09a8..2c37b57 100644 --- a/website/src/contents/blogs/id-ID/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/id-ID/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Berikut yang lain kami kirimkan minggu ini: ### Content & Partnerships - Chris di podcast [@mobymedia](https://x.com/mobymedia): [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- Menerbitkan podcast bukti zero-knowledge pasca-kuantum dengan [@ethan_t_c_](https://x.com/ethan_t_c_) dan [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- Menerbitkan podcast bukti zero-knowledge pasca-kuantum dengan [@ethan*t_c*](https://x.com/ethan_t_c_) dan [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - Menghadiri GitEx di Singapura. - Meng-host sesi full house dengan Dr. [@zina_cinker](https://x.com/zina_cinker) di Network School: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris bergabung dengan [@ArcanumVentures](https://x.com/ArcanumVentures) ep. 47 live Kamis 16 April, 14.00 UTC / 22.00 Singapura: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/ja-JP/weekly-update-04-15-2026.md b/website/src/contents/blogs/ja-JP/weekly-update-04-15-2026.md index fc39037..b8ee52b 100644 --- a/website/src/contents/blogs/ja-JP/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/ja-JP/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Quantus をマイニングしているなら、いまからプランク・テス ### Content & Partnerships - Chris が [@mobymedia](https://x.com/mobymedia) のポッドキャストに出演: [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- [@ethan_t_c_](https://x.com/ethan_t_c_) と [@YuviLightman](https://x.com/YuviLightman) とのポスト量子ゼロ知識証明ポッドキャストを公開: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- [@ethan*t_c*](https://x.com/ethan_t_c_) と [@YuviLightman](https://x.com/YuviLightman) とのポスト量子ゼロ知識証明ポッドキャストを公開: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - シンガポールの GitEx に参加。 - Dr. [@zina_cinker](https://x.com/zina_cinker) との満席セッションを Network School で開催: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris が [@ArcanumVentures](https://x.com/ArcanumVentures) ep. 47 に出演(4 月 16 日木曜 14:00 UTC / シンガポール 22:00): [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/ko-KR/weekly-update-04-15-2026.md b/website/src/contents/blogs/ko-KR/weekly-update-04-15-2026.md index 780f99f..aef53db 100644 --- a/website/src/contents/blogs/ko-KR/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/ko-KR/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Quantus를 채굴 중이라면 지금 바로 플랑크 테스트넷 채굴을 ### Content & Partnerships - Chris, [@mobymedia](https://x.com/mobymedia) 팟캐스트: [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- [@ethan_t_c_](https://x.com/ethan_t_c_) 및 [@YuviLightman](https://x.com/YuviLightman)과 포스트 퀀텀 영지식 증명 팟캐스트 공개: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- [@ethan*t_c*](https://x.com/ethan_t_c_) 및 [@YuviLightman](https://x.com/YuviLightman)과 포스트 퀀텀 영지식 증명 팟캐스트 공개: [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - 싱가포르 GitEx 참석. - Dr. [@zina_cinker](https://x.com/zina_cinker)와 Network School에서 만석 세션 진행: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris, [@ArcanumVentures](https://x.com/ArcanumVentures) 47화 라이브(4월 16일 목요일 14:00 UTC / 싱가포르 22:00): [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/ru-RU/weekly-update-04-15-2026.md b/website/src/contents/blogs/ru-RU/weekly-update-04-15-2026.md index c94b218..862df3f 100644 --- a/website/src/contents/blogs/ru-RU/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/ru-RU/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Quantus — это proof of work. Максимальное предложени ### Content & Partnerships - Chris в подкасте [@mobymedia](https://x.com/mobymedia): [https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- Выпущен подкаст о пост-квантовых доказательствах с нулевым разглашением с [@ethan_t_c_](https://x.com/ethan_t_c_) и [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- Выпущен подкаст о пост-квантовых доказательствах с нулевым разглашением с [@ethan*t_c*](https://x.com/ethan_t_c_) и [@YuviLightman](https://x.com/YuviLightman): [https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - Участие в GitEx в Сингапуре. - Полный зал на сессии с Dr. [@zina_cinker](https://x.com/zina_cinker) в Network School: [https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris в эфире [@ArcanumVentures](https://x.com/ArcanumVentures), выпуск 47, в четверг 16 апреля, 14:00 UTC / 22:00 по Сингапуру: [https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/contents/blogs/zh-CN/weekly-update-04-15-2026.md b/website/src/contents/blogs/zh-CN/weekly-update-04-15-2026.md index a5febe3..911b770 100644 --- a/website/src/contents/blogs/zh-CN/weekly-update-04-15-2026.md +++ b/website/src/contents/blogs/zh-CN/weekly-update-04-15-2026.md @@ -72,7 +72,7 @@ Quantus 采用工作量证明,最大供应量为 2,100 万 QUAN。 ### Content & Partnerships - Chris 做客 [@mobymedia](https://x.com/mobymedia) 播客:[https://x.com/mobymedia/status/2043401794227949568](https://x.com/mobymedia/status/2043401794227949568) -- 与 [@ethan_t_c_](https://x.com/ethan_t_c_) 和 [@YuviLightman](https://x.com/YuviLightman) 发布后量子零知识证明播客:[https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) +- 与 [@ethan*t_c*](https://x.com/ethan_t_c_) 和 [@YuviLightman](https://x.com/YuviLightman) 发布后量子零知识证明播客:[https://x.com/QuantusNetwork/status/2042047089660563948](https://x.com/QuantusNetwork/status/2042047089660563948) - 出席新加坡 GitEx。 - 在 Network School 与 Dr. [@zina_cinker](https://x.com/zina_cinker) 举办满座场次:[https://x.com/QuantusNetwork/status/2044051045832384538](https://x.com/QuantusNetwork/status/2044051045832384538) - Chris 参加 [@ArcanumVentures](https://x.com/ArcanumVentures) 第 47 期直播(4 月 16 日周四 14:00 UTC / 新加坡 22:00):[https://x.com/ArcanumVentures/status/2044023122102223157](https://x.com/ArcanumVentures/status/2044023122102223157) diff --git a/website/src/pages/[lang]/404.astro b/website/src/pages/[lang]/404.astro new file mode 100644 index 0000000..e3e6f91 --- /dev/null +++ b/website/src/pages/[lang]/404.astro @@ -0,0 +1,32 @@ +--- +import Layout from "@/components/layout/Layout.astro"; +import Button from "@/components/ui/Button.astro"; +import { createMetadata } from "@/utils/create-metadata"; +import { SUPPORTED_LOCALES } from "@/utils/i18n"; + +export async function getStaticPaths() { + return SUPPORTED_LOCALES.map((lang) => ({ params: { lang } })); +} + +const metadata = createMetadata({ + title: "404 Not Found", + description: "The page you are looking for could not be found.", + pathname: Astro.url.pathname, + noindex: true, + nofollow: true, +}); +--- + + +
+
+

+ 404 Not found +

+ + +
+
+
diff --git a/website/src/pages/[lang]/privacy-policy.astro b/website/src/pages/[lang]/privacy-policy.astro index d4d9a2f..985a76e 100644 --- a/website/src/pages/[lang]/privacy-policy.astro +++ b/website/src/pages/[lang]/privacy-policy.astro @@ -229,7 +229,7 @@ const additionalInfoRegulatoryItems = t(

{t("privacy.contact_info.note")}{" "} - + {t("privacy.contact_info.link")}

diff --git a/website/src/pages/privacy-policy.astro b/website/src/pages/privacy-policy.astro index e78eb5e..a38f77d 100644 --- a/website/src/pages/privacy-policy.astro +++ b/website/src/pages/privacy-policy.astro @@ -221,7 +221,7 @@ const additionalInfoRegulatoryItems = t(

{t("privacy.contact_info.note")}{" "} - + {t("privacy.contact_info.link")}

diff --git a/website/unlighthouse.config.ts b/website/unlighthouse.config.ts index 72cee80..cd81f6b 100644 --- a/website/unlighthouse.config.ts +++ b/website/unlighthouse.config.ts @@ -18,18 +18,18 @@ export default defineUnlighthouseConfig({ throttle: true, include: [ "/", + "/technology", + "/wallet", + "/community", + "/whitepaper", "/blog", - "/blog/podcast-episode-1", - "/blog/tags/podcast", - "/quests/raid", + "/blog/weekly-update-10-14-2025", "/404", "/about", "/account", - "/app", - "/contact", - "/invite", "/quantum-risk-checker", - "/terms-and-privacy", + "/privacy-policy", + "/terms", ], }, });