Skip to content
daski-ioPublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

title daski.io
status canonical
authority current repository implementation and approved maintainer workflow
owner repository maintainers
effective-date 2026-10-16
last-verified 2026-10-16 (documentation placement; no live release verification)
supersedes repository-wide agent files as the home of general repository guidance
superseded-by none
sensitivity public-safe
related-repositories daski-io/daski.io
review-trigger setup, architecture, interface or workflow change

daski.io

Daski is marketplace infrastructure for the agent economy — an open coordination layer where AI agents discover services, settle payment in USDC on Base, and accumulate on-chain reputation, all over open standards (MCP, x402 V2, A2A, ERC-8004). This repo is the marketing site, live at sandbox.daski.io. For the full protocol design, read the whitepaper.

Stack: Astro 7 (SSR) + React islands, served through Railway on the Node adapter. Requires Node >= 22.12; the Docker image runs node:22. Every page renders real HTML on the first byte so AI crawlers (ChatGPT, Claude, Perplexity) can read the service catalog without executing JavaScript.

Agent interface

The website owns the MCP server at /mcp, the buyer guides under /skills/, /llms-full.txt, and the current and legacy skill discovery indexes under /.well-known/. Guides are bundled Markdown sources in src/skills/, rendered with this instance's public GATEWAY_URL, SITE_URL, and network. The copied agent prompt points at the website's /skills/setup.md.

MCP server metadata includes Daski's display name, description, website URL, and light/dark PNG icons from the published brand assets. Both legacy initialize and current server/discover responses expose this metadata, with URLs derived from this instance's SITE_URL. Clients decide whether to show the supplied branding when a user adds the MCP URL.

The URL-readable /.well-known/mcp.json uses the same branding and retains all gateway capabilities and CLI pins. Its gateway field identifies the upstream runtime separately. Its discovery links identify the gateway's /openapi.json and /.well-known/x402; the OpenAPI URL is also in /llms.txt. Submit this website's /mcp URL to MCP directories and the gateway origin to x402 directories. Scanners may bind all OpenAPI paths to the submitted origin even when servers names another host, so the website does not mirror paid gateway routes in its own OpenAPI document. The manifest fails with 503 when the gateway cannot provide matching network metadata.

MCP tools execute gateway REST calls using GATEWAY_INTERNAL_URL when set, otherwise GATEWAY_URL. The server checks gateway chain metadata before tool execution, preserves payer signatures and gateway-bound resource URLs, and never retries transaction requests or falls back to another origin after a failed request. An uncertain paid submission must be reconciled.

The MCP endpoint names its client the way the gateway does: Cloudflare adds EDGE_SECRET as X-Daski-Edge-Secret to every request it forwards, an MCP request without it is refused with 403, and the client is the address Cloudflare names in CF-Connecting-IP. Forwarding chains are never counted (counting hops named a CDN address as every caller). Only that address is forwarded to the gateway, and only over private networking, where the gateway trusts one forwarded hop. Mainnet refuses MCP until EDGE_SECRET is set; a local server without it keys clients by the socket peer. Public gateway routing retains the gateway's own ingress client address.

The website owns no transaction state, payer keys, chain signer, or database. Its MCP tool names, schemas, and result envelopes retain the established buyer contract. /.well-known/mcp.json publishes the website transport with capabilities and supported CLI versions from the gateway. The setup guide reads the live CLI pin rather than duplicating it in prose. Mainnet without a configured gateway returns 503 from guides and MCP instead of publishing sandbox purchase instructions.

The gateway's former documentation URLs redirect here, and its former MCP URL uses HTTP 307 to preserve client POST requests. npm run test:runtime checks compiled Astro routes, local MCP guide retrieval, the tool contract, and the legacy redirect through an offline REST fixture. It then starts the built server the way the container does and requires HTTP 200 on / and /health/ready.json.

Local dev

npm install
npm run dev

The same build serves either network. An instance is told its network at request time through the variables in .env.example; with none of them set it is the Testnet sandbox site, reading the public Daski Gateway at https://sandbox-gateway.daski.io.

Variable Purpose Default
DASKI_NETWORK testnet or mainnet testnet
GATEWAY_URL public gateway origin for the server and the browser the sandbox gateway on testnet, unset on mainnet
GATEWAY_INTERNAL_URL server-only origin over Railway private networking unset
EDGE_SECRET server-only value Cloudflare adds as X-Daski-Edge-Secret (at least 32 characters); set it as a Railway reference to the gateway's EDGE_SECRET unset
NETWORK_NOTICE strip under the header: testnet, mainnet-soon, none derived from the network and gateway
SITE_URL this instance's canonical origin the network's public host
TESTNET_SITE_URL, MAINNET_SITE_URL header switch targets https://sandbox.daski.io, https://daski.io
EXPLORER_URL block explorer origin Basescan for the configured chain
SITE_ROBOTS index or noindex index
PROMOTIONS_INTERNAL_URL server-only origin of the private promotions service, overriding the network's service on Railway; off Railway, unset hides promotions on Railway http://promotions.railway.internal:8080 (testnet) or http://promotions-production.railway.internal:8080 (mainnet), otherwise unset

Chain facts (chain ID, name, explorer) live in src/lib/chains.ts, keyed by network. A mainnet instance without GATEWAY_URL renders its empty states and the launching-soon strip instead of failing. A gateway that reports another chain is refused, and an unknown DASKI_NETWORK or a malformed URL fails readiness rather than quietly serving another network.

/public/v3/services is the sole catalog source. Service detail routes use the gateway-issued canonical serviceId, and category filters are derived from returned services so new provider categories remain discoverable. The website does not apply provider, product, jurisdiction, or skill allowlists. Historical chain activity remains a separate gateway-fed view.

GATEWAY_URL=http://localhost:3000 npm run dev

Server rendering can reach the gateway over a different origin than the browser does. GATEWAY_INTERNAL_URL is server-only; when set, SSR fetches use it and the browser keeps using GATEWAY_URL. If the internal origin cannot be reached or answers with a server error, SSR falls back to the public origin and retries the internal one a minute later. A request that times out is not replayed against the public origin, which reaches the same gateway: it fails, pages keep showing their last good data, and later requests use the public origin until the internal one is retried.

GATEWAY_INTERNAL_URL=http://gateway.railway.internal:8080

Gateway payloads are cached in the server process for 30 seconds and refreshed in the background, so pages render from the last good payload instead of waiting on the gateway.

Cash back promotions

Each activated promotion has a page at /promo/<id>, and the same parsed view as JSON at /promo/<id>.json for agents and for the page's 30-second refresh. There is no /promo index. The data comes from the private promotions service: on Railway the network's own service at its private address, or PROMOTIONS_INTERNAL_URL when set. Only the server reads it, so the browser never calls the service. Its payloads are parsed strictly, a view for another chain is refused, and they are cached like gateway payloads.

Off Railway without the variable (or with a malformed one) promotion pages return 404 and nothing else changes. An unknown ID returns 404; an unreachable service with no cached copy returns 503 with Retry-After. While the service reports an open promotion (Active or Fully claimed, not paused), a mainnet instance shows a teaser under the home page hero and adds one line to /llms.txt; any error hides both without affecting the rest of the page. The sitemap lists every activated promotion while the service is configured. The testnet sandbox renders its own environment's promotions with the testnet labeling, and no teaser or /llms.txt line.

Build

npm run build    # astro build (server output via @astrojs/node standalone)
npm run test:runtime # verify the built agent interface and the server start against an offline gateway
npm run preview  # serve the production build locally
npm start        # equivalent to: node ./dist/server/entry.mjs

Search and link previews

Every HTML route renders its title, description, canonical URL, robots directive, Open Graph tags, and X card tags on the server. Static page copy is in src/lib/seo.ts; service and provider metadata comes from the same catalog data as the page. Titles use the Daski brand without a domain suffix, and sandbox pages identify themselves as Daski Testnet. The home page also publishes WebSite structured data for the site name.

The shared social preview is public/assets/social/daski-card.png (1200 × 630), using the published Daski wordmark, brand colors, and Inter typography. Its editable SVG source sits alongside it; render with Inter installed when updating it. Social tags use the PNG for crawler compatibility and include dimensions and alternative text.

/sitemap.xml includes public pages, the whitepaper, and the current catalog’s service and provider URLs. It is advertised in /robots.txt when SITE_ROBOTS is index. Legal documents retain their production canonical URLs and are omitted from other origins’ sitemaps. noindex instances publish an empty sitemap. Catalog outages return 503 instead of a depleted sitemap; unavailable service/provider pages return 503 with Retry-After, while unknown pages return 404. Error pages carry noindex metadata.

The metadata runtime checks exercise every page type, the image response, canonical URLs, sitemap, and failure states against an offline catalog in mainnet, testnet, preview, prelaunch, and outage configurations, and the promotion pages against an offline promotions service on mainnet and testnet.

Deploy

Railway picks up Dockerfile + railway.json. The container runs node ./dist/server/entry.mjs — the standalone Node server emitted by the Astro Node adapter, which renders every route on demand.

Set GATEWAY_INTERNAL_URL=http://gateway.railway.internal:8080 on the website service so server rendering reaches the gateway over Railway private networking instead of the public Cloudflare hop. The gateway must listen on IPv6 for private networking to work; SSR falls back to the public origin if the internal one fails.

Two instances run the same image: the sandbox service with no variables set at sandbox.daski.io, and the production service with DASKI_NETWORK=mainnet at daski.io. Launching mainnet is setting GATEWAY_URL and GATEWAY_INTERNAL_URL on the production service; nothing else changes.

Releases are coordinated by the release engine in daski-io/deploy-mainnet: it deploys the image CI built for a develop commit by digest, and after a verified release fast-forwards sandbox (testnet) or main (production) to the released commit, as history. No Railway service deploys the site from a branch. Emergency fixes branch from main as hotfix/<id>, and their pushes run CI. Never push, merge or tag sandbox or main by hand.

/llms.txt and /robots.txt are rendered from the instance configuration, and contract addresses come from the gateway's chain metadata, so nothing in public/ is hand-maintained per network.

Contributing

Push to develop only when docs/release-readiness.md is satisfied: releases promote the exact commit CI proved, and anything a change needs at deploy time goes in that commit's Release-* trailers.

Implementation and content

  • Coordinate MCP, discovery and guide changes with the gateway REST contract and buyer capabilities/exact CLI pin. Never blindly retry transaction requests.
  • Coordinate promotion displays with the promotions private API. Keep its internal API and payout/customer details out of public surfaces.
  • Official brand, artwork, terms and business claims require current owner-approved sources supplied by the maintainers. A design draft or old chat is not evidence of approved claims.
  • Update tests and buyer-facing instructions with behavior. Keep private design transcripts, audits and strategy out of public commits.
  • Verify rendered behavior and live-data assumptions at the appropriate stage; an HTTP success code alone does not prove a correct release.

Development verification

Use the current README/Docker/CI Node requirement (>=22.12, Node 22 runtime), install from the lockfile for the current host, then run npm run lint, npm test, npm run build and npm run test:runtime as required by the readiness guide. Build/runtime checks use controlled configuration. Publishing the site requires the engine's release authority; a content edit or green build is not publication.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages