Website audit
An independent-style technical review of the public website at useweft.ink: how it is delivered, how it is protected, how fast it loads, how accessible it is and how it behaves when things go wrong. Findings are listed with their status. Everything measured here is reproducible with the tools named below.
The web application served at useweft.ink: HTML, JavaScript, CSS, fonts, images, the read-only /api/chain proxy and the HTTP layer in front of them.
Out of scope: the smart contracts the site talks to (perpetual, index registry, token) and the wallet software you connect with. This page makes no claims about them. It is not a security audit of on-chain code.
Method: Lighthouse 12 (desktop and simulated mobile), axe-core 4.10 against WCAG 2.1 A/AA, HTTP header and delivery inspection, manual review of loading, empty and error states. Run on 9 September 2026 against the current release.
Scores
Lighthouse, landing page. Mobile is a simulated mid-range phone on throttled 4G, which is why it is lower than desktop.
| Metric | Desktop | Mobile (simulated) |
|---|---|---|
| First contentful paint | 0.5 s | 2.5 s |
| Largest contentful paint | 0.6 s | 3.0 s |
| Total blocking time | 0 ms | 110–160 ms |
| Cumulative layout shift | 0.007 | 0.075 |
| Time to first byte (edge, cold) | ~0.3 s | |
Findings
Severity reflects impact on visitors, not exploitability. "Fixed" means the change is in the current release.
| Sev. | Area | Finding | Status |
|---|---|---|---|
| High | Delivery | The main script (790 KB) and stylesheets were served uncompressed. Now Brotli or gzip depending on the browser: the script is 223 KB on the wire. | Fixed |
| High | Delivery | No cache headers on any asset, so every visit re-downloaded everything. Hashed assets, fonts and logos are now cached for a year as immutable; HTML revalidates on every load. | Fixed |
| High | Security | No security headers. Added a Content Security Policy (scripts only from this origin, connections only to this origin and the chain RPC, no framing), X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Cross-Origin-Opener-Policy and HSTS for one year. | Fixed |
| Med | Security | The site could be embedded in third-party frames, which matters for anything that talks to a wallet. Framing is now refused at both the CSP and X-Frame-Options level. | Fixed |
| Med | Accessibility | Low-contrast text: secondary captions, the ticker strip and footer labels were between 2.3:1 and 4.5:1. Colours adjusted; every page now passes WCAG AA contrast with zero axe violations. | Fixed |
| Med | Accessibility | The duplicated ticker strip (marked hidden for screen readers) still contained keyboard-focusable links. Removed from the tab order. | Fixed |
| Med | Accessibility | Pages had no h1, and the landing page jumped from h1 to h3. Headline elements now carry the correct levels. | Fixed |
| Med | SEO | No robots.txt or sitemap, and unknown URLs returned 200 with the landing page (soft 404). Both files exist now, and unknown paths return a real 404 with a designed page. | Fixed |
| Med | SEO | No Open Graph or Twitter Card metadata and no canonical URL, so shared links had no preview. Added, with a 1200×630 preview image. | Fixed |
| Low | Performance | The font stylesheet was a separate render-blocking request. It is now inlined in the HTML; font files are self-hosted. | Fixed |
| Low | Performance | Responses from the /api/chain proxy (up to 10 KB of hex) were uncompressed. Now gzipped above 1 KB. | Fixed |
| Low | Reliability | Two tickers without a logo produced 404 requests on every page that showed them. Placeholder monograms are served instead. | Fixed |
| Low | Reliability | Loading states were plain dashes and a line of text with no upper bound. Skeleton placeholders now stand in for content, and a "still reading" notice appears after nine seconds if the chain has not answered. | Fixed |
| Med | Performance | Single 790 KB script bundle with roughly 145 KB unused on the landing page. Splitting it by route needs a source-level build change, not a delivery tweak. Mobile largest-contentful-paint of about 3 s is mostly script start-up on a throttled CPU. | Open |
| Low | Performance | Company logos are served as 128 px PNGs into 22 px slots (about 4 KB each, cached). Smaller variants would save a few kilobytes per page. | Open |
| Low | Delivery | www.useweft.ink does not resolve. Visitors who type it get nothing rather than a redirect. Needs a DNS record and a redirect to the apex domain. | Open |
| Low | Best practices | No source maps are published, which costs a few Lighthouse points and makes production errors harder to read. Deliberate for now. | Accepted |
| Low | Security | The CSP allows inline styles ('unsafe-inline' for style-src) because the application sets styles from JavaScript. Scripts remain restricted to this origin. | Accepted |
Privacy and third parties
- No analytics, no tracking pixels, no cookies, no third-party scripts. Fonts and images are served from this domain.
- The page makes network requests to exactly two places: this origin (including the read-only /api/chain proxy) and the Robinhood Chain public RPC. Both are pinned in the Content Security Policy.
- Outbound links go to the block explorer and the token launchpad page. Nothing is loaded from them.
- The proxy forwards read-only calls and stores nothing. Transactions are signed and sent by your wallet directly; the website never sees a private key.
Reliability
- Chain reads go through the site's proxy first and fall back to the public RPC from the browser if the proxy is unavailable.
- If the chain cannot be reached, pages render their layout with skeletons and, after nine seconds, say so. Nothing silently shows stale numbers as live.
- Positions settle against a thirty-minute time-weighted mark, which the site and the contracts compute identically; the site never invents a price.
- Unknown routes return HTTP 404 with a page that links back to markets. The proxy rejects anything but well-formed read calls.
Response headers
As served by the current release.
content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' https://rpc.mainnet.chain.robinhood.com; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self' strict-transport-security: max-age=31536000; includeSubDomains x-content-type-options: nosniff x-frame-options: DENY referrer-policy: strict-origin-when-cross-origin permissions-policy: camera=(), microphone=(), geolocation=(), payment=() cross-origin-opener-policy: same-origin cache-control: public, max-age=31536000, immutable (hashed assets, fonts, logos) content-encoding: br (text assets, gzip fallback)
How to reproduce
- Headers: curl -sI https://useweft.ink/ and curl -sI -H 'Accept-Encoding: br' https://useweft.ink/assets/ plus the script file name from the page source.
- Lighthouse: Chrome DevTools → Lighthouse, or npx lighthouse https://useweft.ink --preset=desktop. Mobile numbers vary by a few points between runs.
- Accessibility: the axe DevTools extension on any page, WCAG 2.1 A/AA rule set.
This page is updated with each release that changes delivery, headers or accessibility. Last run: 9 September 2026.