[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-sui-walrus-sites":3,"mdc--dyxnom-key":36,"related-org-sui-walrus-sites":978,"related-repo-sui-walrus-sites":1149},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":25,"repoUrl":26,"updatedAt":27,"license":28,"forks":29,"topics":30,"repo":31,"sourceUrl":34,"mdContent":35},"walrus-sites","deploy and manage decentralized Walrus Sites","Publishing, updating, and serving decentralized websites on Walrus Sites. Use when the user needs to deploy a frontend to Walrus Sites, run a local portal for testnet, debug site-builder errors, configure ws-resources.json, or manage site object lifecycle (update, destroy, extend blobs). Also use when the user asks about site-builder, walrus-sites, portal setup, or hosting a dApp on Walrus. For blob storage without the Sites framework (raw upload\u002Fdownload), see the `accessing-data` skill's walrus.md.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"sui","Sui (Mysten Labs)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fsui.png","MystenLabs",[13,16,19,22],{"name":14,"slug":8,"type":15},"Sui","tag",{"name":17,"slug":18,"type":15},"Web3","web3",{"name":20,"slug":21,"type":15},"Deployment","deployment",{"name":23,"slug":24,"type":15},"Frontend","frontend",9,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fskills","2026-07-16T06:02:44.270065",null,2,[],{"repoUrl":26,"stars":25,"forks":29,"topics":32,"description":33},[],"Sui development skills maintained by Mysten Labs","https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fskills\u002Ftree\u002FHEAD\u002Fwalrus-sites","---\nname: walrus-sites\ndescription: >\n  Publishing, updating, and serving decentralized websites on Walrus Sites.\n  Use when the user needs to deploy a frontend to Walrus Sites, run a local\n  portal for testnet, debug site-builder errors, configure ws-resources.json,\n  or manage site object lifecycle (update, destroy, extend blobs). Also use\n  when the user asks about site-builder, walrus-sites, portal setup, or\n  hosting a dApp on Walrus. For blob storage without the Sites framework\n  (raw upload\u002Fdownload), see the `accessing-data` skill's walrus.md.\n---\n\n# Walrus Sites — Decentralized Website Hosting\n\n> **MCP tool:** When available in your environment, also query the Sui documentation MCP server (`https:\u002F\u002Fsui.mcp.kapa.ai`) for up-to-date answers. Use it for verification and for details not covered by these reference files.\n\nWalrus Sites lets you deploy a static website (HTML\u002FCSS\u002FJS) to Walrus, with an on-chain Sui object tracking the site's resources. A portal server resolves site subdomains, fetches resources from Walrus, and serves them over HTTP. The result is a fully decentralized frontend — no centralized server, CDN, or DNS required.\n\n> **Source constraint:** All information in this skill is sourced from the [MystenLabs\u002Fwalrus-sites](https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fwalrus-sites) repository and the [Walrus Sites documentation](https:\u002F\u002Fdocs.wal.app\u002Fdocs\u002Fsites). When extending or updating this skill, only pull from these sources. Do not use third-party blogs or unofficial tutorials.\n\nCommon failures:\n\n1. **Blobs expire.** Sites published with too few epochs silently break — the portal returns 404 once the blobs expire. Always use a generous `--epochs` value (30+).\n2. **Portal misconfiguration.** The portal's `original_package_id` must match the Walrus Sites framework package (`site::Site`), not your app's Move package. The testnet example config ships with the correct value — don't change it.\n3. **Testnet sites can't use `wal.app`.** The public `wal.app` portal only serves mainnet sites. Testnet requires a self-hosted local portal.\n4. **SPA routing.** Single-page apps need `ws-resources.json` routes config to handle client-side routing. Without it, direct navigation to `\u002Fmy-route` returns 404.\n\n---\n\n## Sub-skills\n\n### publishing — Building and deploying sites\n**Path:** `publishing\u002FSKILL.md`\n**Load when:** deploying a new site, updating an existing site, choosing epoch duration, configuring `ws-resources.json`, or troubleshooting `site-builder` errors.\n**Covers:** `site-builder publish`, `site-builder update`, `--epochs` flag, blob expiration, `ws-resources.json` configuration, SPA routing, site naming, `site-builder sitemap` for debugging, `site-builder destroy`.\n\n### portal — Running a local portal for testnet\n**Path:** `portal\u002FSKILL.md`\n**Load when:** the user needs to view a testnet site, set up the local portal, fix portal 404s, or understand how portal resolution works.\n**Covers:** cloning the portal, installing dependencies (Bun), `portal-config.yaml`, the `original_package_id` gotcha, starting the server, URL format, port conflicts, mainnet vs testnet differences.\n\n---\n\n## Routing guide\n\n| Task | Load |\n|------|------|\n| Deploy a frontend to Walrus Sites | `publishing\u002F` |\n| Update an existing deployed site | `publishing\u002F` |\n| Fix 404 or expired site | `publishing\u002F` + `portal\u002F` |\n| View a testnet site locally | `portal\u002F` |\n| Set up the local portal | `portal\u002F` |\n| Portal shows \"Page not found\" | `portal\u002F` + `publishing\u002F` (check blob expiry) |\n| Configure SPA routing | `publishing\u002F` |\n| Check what resources a site has | `publishing\u002F` (`site-builder sitemap`) |\n| Delete a deployed site | `publishing\u002F` |\n| Choose between Walrus Sites and traditional hosting | Skill Content below |\n\n---\n\n## Skill Content\n\n### Key concepts\n\n- **Site object.** A Sui object of type `site::Site` (from the Walrus Sites framework package). It holds metadata (name, description) and dynamic fields mapping resource paths to Walrus blob references. Created by `site-builder publish`, owned by the publisher's address.\n\n- **Resources.** Each file in the deployed directory becomes a resource stored on Walrus. Small files may be batched into a single \"quilt\" blob. Each resource has a path (e.g., `\u002Findex.html`, `\u002Fassets\u002Fmain.js`) and optional HTTP headers.\n\n- **Portal.** A server that maps `\u003Cbase36-site-id>.localhost:3000` URLs to on-chain site objects. It reads the site's dynamic fields to find the requested resource path, fetches the blob from a Walrus aggregator, and returns it as an HTTP response. The portal is framework-level infrastructure, not part of your app.\n\n- **`ws-resources.json`.** A configuration file in the site's root directory that controls resource headers, routing, and site metadata. Auto-generated on first publish with the site object ID. On subsequent runs, the site-builder reads it to determine whether to create a new site or update the existing one.\n\n- **Blob expiration.** Walrus blobs have a finite storage duration measured in epochs. When blobs expire, the portal can no longer fetch them and returns 404. Use `site-builder sitemap \u003Cobject-id>` to check expiration dates. Re-publish with a higher `--epochs` value to fix.\n\n### Rules\n\n1. **Always use `--epochs 30` or higher for testnet deploys.** Low values (like 5) cause blobs to expire within days. For production mainnet, use even higher values or `--permanent`.\n2. **Build before publishing.** Run `npm run build` (or equivalent) to produce a static `dist\u002F` directory. The site-builder publishes whatever directory you point it at.\n3. **Don't change `original_package_id` in the portal config** unless you know the Walrus Sites framework package has been upgraded. The testnet example value is correct.\n4. **`wal.app` is mainnet only.** For testnet, self-host the portal from the `MystenLabs\u002Fwalrus-sites` repo.\n5. **Check `ws-resources.json` after first publish.** It records the site object ID. Keep it in version control so future publishes update the existing site rather than creating a new one.\n\n### Common mistakes\n\n- **Publishing with `--epochs 5` and wondering why the site is gone a week later.** Blobs expired. Re-publish with `--epochs 30+`.\n- **Changing the portal's `original_package_id` to your app's package ID.** The portal needs the Walrus Sites framework package ID (`site::Site`), not your Move contract's package ID. These are completely different things.\n- **Trying to visit a testnet site on `wal.app`.** It only serves mainnet. You need a local portal for testnet.\n- **Forgetting to build the frontend before publishing.** `site-builder publish dist\u002F` publishes the `dist\u002F` directory contents. If you didn't `npm run build` first, you're publishing source files or stale output.\n- **Deploying an SPA without fallback routing.** React\u002FVue\u002FSvelte SPAs use client-side routing. Direct navigation to `\u002Fborrows` hits the portal, which looks for `\u002Fborrows` as a resource — and it doesn't exist. Configure a fallback in `ws-resources.json`.\n- **Not killing port 3000 before starting the portal.** Vite dev server, Next.js, or other tools often use port 3000. The portal silently fails to bind if the port is taken.\n",{"data":37,"body":38},{"name":4,"description":6},{"type":39,"children":40},"root",[41,50,75,80,113,118,218,222,229,236,324,330,371,374,380,591,594,600,606,716,722,832,838],{"type":42,"tag":43,"props":44,"children":46},"element","h1",{"id":45},"walrus-sites-decentralized-website-hosting",[47],{"type":48,"value":49},"text","Walrus Sites — Decentralized Website Hosting",{"type":42,"tag":51,"props":52,"children":53},"blockquote",{},[54],{"type":42,"tag":55,"props":56,"children":57},"p",{},[58,64,66,73],{"type":42,"tag":59,"props":60,"children":61},"strong",{},[62],{"type":48,"value":63},"MCP tool:",{"type":48,"value":65}," When available in your environment, also query the Sui documentation MCP server (",{"type":42,"tag":67,"props":68,"children":70},"code",{"className":69},[],[71],{"type":48,"value":72},"https:\u002F\u002Fsui.mcp.kapa.ai",{"type":48,"value":74},") for up-to-date answers. Use it for verification and for details not covered by these reference files.",{"type":42,"tag":55,"props":76,"children":77},{},[78],{"type":48,"value":79},"Walrus Sites lets you deploy a static website (HTML\u002FCSS\u002FJS) to Walrus, with an on-chain Sui object tracking the site's resources. A portal server resolves site subdomains, fetches resources from Walrus, and serves them over HTTP. The result is a fully decentralized frontend — no centralized server, CDN, or DNS required.",{"type":42,"tag":51,"props":81,"children":82},{},[83],{"type":42,"tag":55,"props":84,"children":85},{},[86,91,93,102,104,111],{"type":42,"tag":59,"props":87,"children":88},{},[89],{"type":48,"value":90},"Source constraint:",{"type":48,"value":92}," All information in this skill is sourced from the ",{"type":42,"tag":94,"props":95,"children":99},"a",{"href":96,"rel":97},"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fwalrus-sites",[98],"nofollow",[100],{"type":48,"value":101},"MystenLabs\u002Fwalrus-sites",{"type":48,"value":103}," repository and the ",{"type":42,"tag":94,"props":105,"children":108},{"href":106,"rel":107},"https:\u002F\u002Fdocs.wal.app\u002Fdocs\u002Fsites",[98],[109],{"type":48,"value":110},"Walrus Sites documentation",{"type":48,"value":112},". When extending or updating this skill, only pull from these sources. Do not use third-party blogs or unofficial tutorials.",{"type":42,"tag":55,"props":114,"children":115},{},[116],{"type":48,"value":117},"Common failures:",{"type":42,"tag":119,"props":120,"children":121},"ol",{},[122,141,167,192],{"type":42,"tag":123,"props":124,"children":125},"li",{},[126,131,133,139],{"type":42,"tag":59,"props":127,"children":128},{},[129],{"type":48,"value":130},"Blobs expire.",{"type":48,"value":132}," Sites published with too few epochs silently break — the portal returns 404 once the blobs expire. Always use a generous ",{"type":42,"tag":67,"props":134,"children":136},{"className":135},[],[137],{"type":48,"value":138},"--epochs",{"type":48,"value":140}," value (30+).",{"type":42,"tag":123,"props":142,"children":143},{},[144,149,151,157,159,165],{"type":42,"tag":59,"props":145,"children":146},{},[147],{"type":48,"value":148},"Portal misconfiguration.",{"type":48,"value":150}," The portal's ",{"type":42,"tag":67,"props":152,"children":154},{"className":153},[],[155],{"type":48,"value":156},"original_package_id",{"type":48,"value":158}," must match the Walrus Sites framework package (",{"type":42,"tag":67,"props":160,"children":162},{"className":161},[],[163],{"type":48,"value":164},"site::Site",{"type":48,"value":166},"), not your app's Move package. The testnet example config ships with the correct value — don't change it.",{"type":42,"tag":123,"props":168,"children":169},{},[170,183,185,190],{"type":42,"tag":59,"props":171,"children":172},{},[173,175,181],{"type":48,"value":174},"Testnet sites can't use ",{"type":42,"tag":67,"props":176,"children":178},{"className":177},[],[179],{"type":48,"value":180},"wal.app",{"type":48,"value":182},".",{"type":48,"value":184}," The public ",{"type":42,"tag":67,"props":186,"children":188},{"className":187},[],[189],{"type":48,"value":180},{"type":48,"value":191}," portal only serves mainnet sites. Testnet requires a self-hosted local portal.",{"type":42,"tag":123,"props":193,"children":194},{},[195,200,202,208,210,216],{"type":42,"tag":59,"props":196,"children":197},{},[198],{"type":48,"value":199},"SPA routing.",{"type":48,"value":201}," Single-page apps need ",{"type":42,"tag":67,"props":203,"children":205},{"className":204},[],[206],{"type":48,"value":207},"ws-resources.json",{"type":48,"value":209}," routes config to handle client-side routing. Without it, direct navigation to ",{"type":42,"tag":67,"props":211,"children":213},{"className":212},[],[214],{"type":48,"value":215},"\u002Fmy-route",{"type":48,"value":217}," returns 404.",{"type":42,"tag":219,"props":220,"children":221},"hr",{},[],{"type":42,"tag":223,"props":224,"children":226},"h2",{"id":225},"sub-skills",[227],{"type":48,"value":228},"Sub-skills",{"type":42,"tag":230,"props":231,"children":233},"h3",{"id":232},"publishing-building-and-deploying-sites",[234],{"type":48,"value":235},"publishing — Building and deploying sites",{"type":42,"tag":55,"props":237,"children":238},{},[239,244,246,252,257,259,264,266,272,274,279,280,286,288,294,295,300,302,307,309,315,317,323],{"type":42,"tag":59,"props":240,"children":241},{},[242],{"type":48,"value":243},"Path:",{"type":48,"value":245}," ",{"type":42,"tag":67,"props":247,"children":249},{"className":248},[],[250],{"type":48,"value":251},"publishing\u002FSKILL.md",{"type":42,"tag":59,"props":253,"children":254},{},[255],{"type":48,"value":256},"Load when:",{"type":48,"value":258}," deploying a new site, updating an existing site, choosing epoch duration, configuring ",{"type":42,"tag":67,"props":260,"children":262},{"className":261},[],[263],{"type":48,"value":207},{"type":48,"value":265},", or troubleshooting ",{"type":42,"tag":67,"props":267,"children":269},{"className":268},[],[270],{"type":48,"value":271},"site-builder",{"type":48,"value":273}," errors.\n",{"type":42,"tag":59,"props":275,"children":276},{},[277],{"type":48,"value":278},"Covers:",{"type":48,"value":245},{"type":42,"tag":67,"props":281,"children":283},{"className":282},[],[284],{"type":48,"value":285},"site-builder publish",{"type":48,"value":287},", ",{"type":42,"tag":67,"props":289,"children":291},{"className":290},[],[292],{"type":48,"value":293},"site-builder update",{"type":48,"value":287},{"type":42,"tag":67,"props":296,"children":298},{"className":297},[],[299],{"type":48,"value":138},{"type":48,"value":301}," flag, blob expiration, ",{"type":42,"tag":67,"props":303,"children":305},{"className":304},[],[306],{"type":48,"value":207},{"type":48,"value":308}," configuration, SPA routing, site naming, ",{"type":42,"tag":67,"props":310,"children":312},{"className":311},[],[313],{"type":48,"value":314},"site-builder sitemap",{"type":48,"value":316}," for debugging, ",{"type":42,"tag":67,"props":318,"children":320},{"className":319},[],[321],{"type":48,"value":322},"site-builder destroy",{"type":48,"value":182},{"type":42,"tag":230,"props":325,"children":327},{"id":326},"portal-running-a-local-portal-for-testnet",[328],{"type":48,"value":329},"portal — Running a local portal for testnet",{"type":42,"tag":55,"props":331,"children":332},{},[333,337,338,344,348,350,354,356,362,364,369],{"type":42,"tag":59,"props":334,"children":335},{},[336],{"type":48,"value":243},{"type":48,"value":245},{"type":42,"tag":67,"props":339,"children":341},{"className":340},[],[342],{"type":48,"value":343},"portal\u002FSKILL.md",{"type":42,"tag":59,"props":345,"children":346},{},[347],{"type":48,"value":256},{"type":48,"value":349}," the user needs to view a testnet site, set up the local portal, fix portal 404s, or understand how portal resolution works.\n",{"type":42,"tag":59,"props":351,"children":352},{},[353],{"type":48,"value":278},{"type":48,"value":355}," cloning the portal, installing dependencies (Bun), ",{"type":42,"tag":67,"props":357,"children":359},{"className":358},[],[360],{"type":48,"value":361},"portal-config.yaml",{"type":48,"value":363},", the ",{"type":42,"tag":67,"props":365,"children":367},{"className":366},[],[368],{"type":48,"value":156},{"type":48,"value":370}," gotcha, starting the server, URL format, port conflicts, mainnet vs testnet differences.",{"type":42,"tag":219,"props":372,"children":373},{},[],{"type":42,"tag":223,"props":375,"children":377},{"id":376},"routing-guide",[378],{"type":48,"value":379},"Routing guide",{"type":42,"tag":381,"props":382,"children":383},"table",{},[384,403],{"type":42,"tag":385,"props":386,"children":387},"thead",{},[388],{"type":42,"tag":389,"props":390,"children":391},"tr",{},[392,398],{"type":42,"tag":393,"props":394,"children":395},"th",{},[396],{"type":48,"value":397},"Task",{"type":42,"tag":393,"props":399,"children":400},{},[401],{"type":48,"value":402},"Load",{"type":42,"tag":404,"props":405,"children":406},"tbody",{},[407,425,441,465,481,497,521,537,562,578],{"type":42,"tag":389,"props":408,"children":409},{},[410,416],{"type":42,"tag":411,"props":412,"children":413},"td",{},[414],{"type":48,"value":415},"Deploy a frontend to Walrus Sites",{"type":42,"tag":411,"props":417,"children":418},{},[419],{"type":42,"tag":67,"props":420,"children":422},{"className":421},[],[423],{"type":48,"value":424},"publishing\u002F",{"type":42,"tag":389,"props":426,"children":427},{},[428,433],{"type":42,"tag":411,"props":429,"children":430},{},[431],{"type":48,"value":432},"Update an existing deployed site",{"type":42,"tag":411,"props":434,"children":435},{},[436],{"type":42,"tag":67,"props":437,"children":439},{"className":438},[],[440],{"type":48,"value":424},{"type":42,"tag":389,"props":442,"children":443},{},[444,449],{"type":42,"tag":411,"props":445,"children":446},{},[447],{"type":48,"value":448},"Fix 404 or expired site",{"type":42,"tag":411,"props":450,"children":451},{},[452,457,459],{"type":42,"tag":67,"props":453,"children":455},{"className":454},[],[456],{"type":48,"value":424},{"type":48,"value":458}," + ",{"type":42,"tag":67,"props":460,"children":462},{"className":461},[],[463],{"type":48,"value":464},"portal\u002F",{"type":42,"tag":389,"props":466,"children":467},{},[468,473],{"type":42,"tag":411,"props":469,"children":470},{},[471],{"type":48,"value":472},"View a testnet site locally",{"type":42,"tag":411,"props":474,"children":475},{},[476],{"type":42,"tag":67,"props":477,"children":479},{"className":478},[],[480],{"type":48,"value":464},{"type":42,"tag":389,"props":482,"children":483},{},[484,489],{"type":42,"tag":411,"props":485,"children":486},{},[487],{"type":48,"value":488},"Set up the local portal",{"type":42,"tag":411,"props":490,"children":491},{},[492],{"type":42,"tag":67,"props":493,"children":495},{"className":494},[],[496],{"type":48,"value":464},{"type":42,"tag":389,"props":498,"children":499},{},[500,505],{"type":42,"tag":411,"props":501,"children":502},{},[503],{"type":48,"value":504},"Portal shows \"Page not found\"",{"type":42,"tag":411,"props":506,"children":507},{},[508,513,514,519],{"type":42,"tag":67,"props":509,"children":511},{"className":510},[],[512],{"type":48,"value":464},{"type":48,"value":458},{"type":42,"tag":67,"props":515,"children":517},{"className":516},[],[518],{"type":48,"value":424},{"type":48,"value":520}," (check blob expiry)",{"type":42,"tag":389,"props":522,"children":523},{},[524,529],{"type":42,"tag":411,"props":525,"children":526},{},[527],{"type":48,"value":528},"Configure SPA routing",{"type":42,"tag":411,"props":530,"children":531},{},[532],{"type":42,"tag":67,"props":533,"children":535},{"className":534},[],[536],{"type":48,"value":424},{"type":42,"tag":389,"props":538,"children":539},{},[540,545],{"type":42,"tag":411,"props":541,"children":542},{},[543],{"type":48,"value":544},"Check what resources a site has",{"type":42,"tag":411,"props":546,"children":547},{},[548,553,555,560],{"type":42,"tag":67,"props":549,"children":551},{"className":550},[],[552],{"type":48,"value":424},{"type":48,"value":554}," (",{"type":42,"tag":67,"props":556,"children":558},{"className":557},[],[559],{"type":48,"value":314},{"type":48,"value":561},")",{"type":42,"tag":389,"props":563,"children":564},{},[565,570],{"type":42,"tag":411,"props":566,"children":567},{},[568],{"type":48,"value":569},"Delete a deployed site",{"type":42,"tag":411,"props":571,"children":572},{},[573],{"type":42,"tag":67,"props":574,"children":576},{"className":575},[],[577],{"type":48,"value":424},{"type":42,"tag":389,"props":579,"children":580},{},[581,586],{"type":42,"tag":411,"props":582,"children":583},{},[584],{"type":48,"value":585},"Choose between Walrus Sites and traditional hosting",{"type":42,"tag":411,"props":587,"children":588},{},[589],{"type":48,"value":590},"Skill Content below",{"type":42,"tag":219,"props":592,"children":593},{},[],{"type":42,"tag":223,"props":595,"children":597},{"id":596},"skill-content",[598],{"type":48,"value":599},"Skill Content",{"type":42,"tag":230,"props":601,"children":603},{"id":602},"key-concepts",[604],{"type":48,"value":605},"Key concepts",{"type":42,"tag":607,"props":608,"children":609},"ul",{},[610,634,659,677,691],{"type":42,"tag":123,"props":611,"children":612},{},[613,618,620,625,627,632],{"type":42,"tag":59,"props":614,"children":615},{},[616],{"type":48,"value":617},"Site object.",{"type":48,"value":619}," A Sui object of type ",{"type":42,"tag":67,"props":621,"children":623},{"className":622},[],[624],{"type":48,"value":164},{"type":48,"value":626}," (from the Walrus Sites framework package). It holds metadata (name, description) and dynamic fields mapping resource paths to Walrus blob references. Created by ",{"type":42,"tag":67,"props":628,"children":630},{"className":629},[],[631],{"type":48,"value":285},{"type":48,"value":633},", owned by the publisher's address.",{"type":42,"tag":123,"props":635,"children":636},{},[637,642,644,650,651,657],{"type":42,"tag":59,"props":638,"children":639},{},[640],{"type":48,"value":641},"Resources.",{"type":48,"value":643}," Each file in the deployed directory becomes a resource stored on Walrus. Small files may be batched into a single \"quilt\" blob. Each resource has a path (e.g., ",{"type":42,"tag":67,"props":645,"children":647},{"className":646},[],[648],{"type":48,"value":649},"\u002Findex.html",{"type":48,"value":287},{"type":42,"tag":67,"props":652,"children":654},{"className":653},[],[655],{"type":48,"value":656},"\u002Fassets\u002Fmain.js",{"type":48,"value":658},") and optional HTTP headers.",{"type":42,"tag":123,"props":660,"children":661},{},[662,667,669,675],{"type":42,"tag":59,"props":663,"children":664},{},[665],{"type":48,"value":666},"Portal.",{"type":48,"value":668}," A server that maps ",{"type":42,"tag":67,"props":670,"children":672},{"className":671},[],[673],{"type":48,"value":674},"\u003Cbase36-site-id>.localhost:3000",{"type":48,"value":676}," URLs to on-chain site objects. It reads the site's dynamic fields to find the requested resource path, fetches the blob from a Walrus aggregator, and returns it as an HTTP response. The portal is framework-level infrastructure, not part of your app.",{"type":42,"tag":123,"props":678,"children":679},{},[680,689],{"type":42,"tag":59,"props":681,"children":682},{},[683,688],{"type":42,"tag":67,"props":684,"children":686},{"className":685},[],[687],{"type":48,"value":207},{"type":48,"value":182},{"type":48,"value":690}," A configuration file in the site's root directory that controls resource headers, routing, and site metadata. Auto-generated on first publish with the site object ID. On subsequent runs, the site-builder reads it to determine whether to create a new site or update the existing one.",{"type":42,"tag":123,"props":692,"children":693},{},[694,699,701,707,709,714],{"type":42,"tag":59,"props":695,"children":696},{},[697],{"type":48,"value":698},"Blob expiration.",{"type":48,"value":700}," Walrus blobs have a finite storage duration measured in epochs. When blobs expire, the portal can no longer fetch them and returns 404. Use ",{"type":42,"tag":67,"props":702,"children":704},{"className":703},[],[705],{"type":48,"value":706},"site-builder sitemap \u003Cobject-id>",{"type":48,"value":708}," to check expiration dates. Re-publish with a higher ",{"type":42,"tag":67,"props":710,"children":712},{"className":711},[],[713],{"type":48,"value":138},{"type":48,"value":715}," value to fix.",{"type":42,"tag":230,"props":717,"children":719},{"id":718},"rules",[720],{"type":48,"value":721},"Rules",{"type":42,"tag":119,"props":723,"children":724},{},[725,750,776,793,815],{"type":42,"tag":123,"props":726,"children":727},{},[728,741,743,749],{"type":42,"tag":59,"props":729,"children":730},{},[731,733,739],{"type":48,"value":732},"Always use ",{"type":42,"tag":67,"props":734,"children":736},{"className":735},[],[737],{"type":48,"value":738},"--epochs 30",{"type":48,"value":740}," or higher for testnet deploys.",{"type":48,"value":742}," Low values (like 5) cause blobs to expire within days. For production mainnet, use even higher values or ",{"type":42,"tag":67,"props":744,"children":746},{"className":745},[],[747],{"type":48,"value":748},"--permanent",{"type":48,"value":182},{"type":42,"tag":123,"props":751,"children":752},{},[753,758,760,766,768,774],{"type":42,"tag":59,"props":754,"children":755},{},[756],{"type":48,"value":757},"Build before publishing.",{"type":48,"value":759}," Run ",{"type":42,"tag":67,"props":761,"children":763},{"className":762},[],[764],{"type":48,"value":765},"npm run build",{"type":48,"value":767}," (or equivalent) to produce a static ",{"type":42,"tag":67,"props":769,"children":771},{"className":770},[],[772],{"type":48,"value":773},"dist\u002F",{"type":48,"value":775}," directory. The site-builder publishes whatever directory you point it at.",{"type":42,"tag":123,"props":777,"children":778},{},[779,791],{"type":42,"tag":59,"props":780,"children":781},{},[782,784,789],{"type":48,"value":783},"Don't change ",{"type":42,"tag":67,"props":785,"children":787},{"className":786},[],[788],{"type":48,"value":156},{"type":48,"value":790}," in the portal config",{"type":48,"value":792}," unless you know the Walrus Sites framework package has been upgraded. The testnet example value is correct.",{"type":42,"tag":123,"props":794,"children":795},{},[796,806,808,813],{"type":42,"tag":59,"props":797,"children":798},{},[799,804],{"type":42,"tag":67,"props":800,"children":802},{"className":801},[],[803],{"type":48,"value":180},{"type":48,"value":805}," is mainnet only.",{"type":48,"value":807}," For testnet, self-host the portal from the ",{"type":42,"tag":67,"props":809,"children":811},{"className":810},[],[812],{"type":48,"value":101},{"type":48,"value":814}," repo.",{"type":42,"tag":123,"props":816,"children":817},{},[818,830],{"type":42,"tag":59,"props":819,"children":820},{},[821,823,828],{"type":48,"value":822},"Check ",{"type":42,"tag":67,"props":824,"children":826},{"className":825},[],[827],{"type":48,"value":207},{"type":48,"value":829}," after first publish.",{"type":48,"value":831}," It records the site object ID. Keep it in version control so future publishes update the existing site rather than creating a new one.",{"type":42,"tag":230,"props":833,"children":835},{"id":834},"common-mistakes",[836],{"type":48,"value":837},"Common mistakes",{"type":42,"tag":607,"props":839,"children":840},{},[841,866,890,906,937,968],{"type":42,"tag":123,"props":842,"children":843},{},[844,857,859,865],{"type":42,"tag":59,"props":845,"children":846},{},[847,849,855],{"type":48,"value":848},"Publishing with ",{"type":42,"tag":67,"props":850,"children":852},{"className":851},[],[853],{"type":48,"value":854},"--epochs 5",{"type":48,"value":856}," and wondering why the site is gone a week later.",{"type":48,"value":858}," Blobs expired. Re-publish with ",{"type":42,"tag":67,"props":860,"children":862},{"className":861},[],[863],{"type":48,"value":864},"--epochs 30+",{"type":48,"value":182},{"type":42,"tag":123,"props":867,"children":868},{},[869,881,883,888],{"type":42,"tag":59,"props":870,"children":871},{},[872,874,879],{"type":48,"value":873},"Changing the portal's ",{"type":42,"tag":67,"props":875,"children":877},{"className":876},[],[878],{"type":48,"value":156},{"type":48,"value":880}," to your app's package ID.",{"type":48,"value":882}," The portal needs the Walrus Sites framework package ID (",{"type":42,"tag":67,"props":884,"children":886},{"className":885},[],[887],{"type":48,"value":164},{"type":48,"value":889},"), not your Move contract's package ID. These are completely different things.",{"type":42,"tag":123,"props":891,"children":892},{},[893,904],{"type":42,"tag":59,"props":894,"children":895},{},[896,898,903],{"type":48,"value":897},"Trying to visit a testnet site on ",{"type":42,"tag":67,"props":899,"children":901},{"className":900},[],[902],{"type":48,"value":180},{"type":48,"value":182},{"type":48,"value":905}," It only serves mainnet. You need a local portal for testnet.",{"type":42,"tag":123,"props":907,"children":908},{},[909,914,915,921,923,928,930,935],{"type":42,"tag":59,"props":910,"children":911},{},[912],{"type":48,"value":913},"Forgetting to build the frontend before publishing.",{"type":48,"value":245},{"type":42,"tag":67,"props":916,"children":918},{"className":917},[],[919],{"type":48,"value":920},"site-builder publish dist\u002F",{"type":48,"value":922}," publishes the ",{"type":42,"tag":67,"props":924,"children":926},{"className":925},[],[927],{"type":48,"value":773},{"type":48,"value":929}," directory contents. If you didn't ",{"type":42,"tag":67,"props":931,"children":933},{"className":932},[],[934],{"type":48,"value":765},{"type":48,"value":936}," first, you're publishing source files or stale output.",{"type":42,"tag":123,"props":938,"children":939},{},[940,945,947,953,955,960,962,967],{"type":42,"tag":59,"props":941,"children":942},{},[943],{"type":48,"value":944},"Deploying an SPA without fallback routing.",{"type":48,"value":946}," React\u002FVue\u002FSvelte SPAs use client-side routing. Direct navigation to ",{"type":42,"tag":67,"props":948,"children":950},{"className":949},[],[951],{"type":48,"value":952},"\u002Fborrows",{"type":48,"value":954}," hits the portal, which looks for ",{"type":42,"tag":67,"props":956,"children":958},{"className":957},[],[959],{"type":48,"value":952},{"type":48,"value":961}," as a resource — and it doesn't exist. Configure a fallback in ",{"type":42,"tag":67,"props":963,"children":965},{"className":964},[],[966],{"type":48,"value":207},{"type":48,"value":182},{"type":42,"tag":123,"props":969,"children":970},{},[971,976],{"type":42,"tag":59,"props":972,"children":973},{},[974],{"type":48,"value":975},"Not killing port 3000 before starting the portal.",{"type":48,"value":977}," Vite dev server, Next.js, or other tools often use port 3000. The portal silently fails to bind if the port is taken.",{"items":979,"total":1148},[980,996,1007,1017,1034,1052,1064,1077,1096,1108,1119,1135],{"slug":981,"name":981,"fn":982,"description":983,"org":984,"tags":985,"stars":993,"repoUrl":994,"updatedAt":995},"move-bytecode-comprehension","analyze and disassemble Move bytecode","Use when reading or reasoning about compiled Move bytecode or `sui move disassemble` output. Mental model for the binary format, what survives compilation (and what's lost), and how to read disassembly soundly. Trigger on \"what does this package do?\", \"read this .mv module\", \"interpret this disassembly\", or whenever an analysis needs to interpret bytecode faithfully.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[986,989,992],{"name":987,"slug":988,"type":15},"Code Analysis","code-analysis",{"name":990,"slug":991,"type":15},"Engineering","engineering",{"name":14,"slug":8,"type":15},7724,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fsui","2026-07-16T05:59:32.904886",{"slug":997,"name":997,"fn":998,"description":999,"org":1000,"tags":1001,"stars":993,"repoUrl":994,"updatedAt":1006},"official-sui-skills","access official Sui development resources","Pointer to the official Mysten Labs skills for building on Sui — language fundamentals, object model, PTBs, SDKs, publishing, upgrades, frontend integration, accessing on-chain data. Maintained upstream at github.com\u002FMystenLabs\u002Fskills; pinned to the same ref the audit catalog derives from (see maintenance\u002FUPSTREAMS.md). Trigger on \"build a contract\", \"publish a package\", \"upgrade a module or package\", \"use the TypeScript SDK\", \"write a PTB\", \"set up a Sui client\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1002,1005],{"name":1003,"slug":1004,"type":15},"Documentation","documentation",{"name":14,"slug":8,"type":15},"2026-07-16T06:00:59.641382",{"slug":1008,"name":1008,"fn":1009,"description":1010,"org":1011,"tags":1012,"stars":993,"repoUrl":994,"updatedAt":1016},"sui-and-move-tools","disassemble Sui Move bytecode","Use to get bytecode for a deployed Sui package and produce a disassembled working view. One GraphQL call fetches every module's raw bytecode bytes; `sui move disassemble` (already on the system, running `sui prompt`) produces `.asm` files for analysis. Trigger on \"fetch this package's bytecode\", \"get me the .mv for package X\", \"disassemble this package\", or \"I need to read a deployed Sui package\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1013,1014,1015],{"name":987,"slug":988,"type":15},{"name":990,"slug":991,"type":15},{"name":14,"slug":8,"type":15},"2026-07-16T06:02:25.3633",{"slug":1018,"name":1018,"fn":1019,"description":1020,"org":1021,"tags":1022,"stars":993,"repoUrl":994,"updatedAt":1033},"sui-move-security-review","audit Sui Move smart contracts","Use when auditing, reviewing, or hunting for vulnerabilities in Move code on Sui. Applies equally to source code (.move files) and to disassembly of compiled bytecode (on-chain packages). A checklist of invariants whose VIOLATION causes exploitable bugs: access control & capabilities, struct abilities & type safety, object lifecycle & ownership, shared-object and PTB attack surface, dynamic fields & collections, arithmetic & coins, init\u002FOTW\u002Fpackage upgrades, hot-potato composability, time & on-chain randomness, and test-only code leakage. Trigger on \"audit this Move code\", \"find vulnerabilities in this Sui contract\", \"security review\", \"is this package safe?\", \"I suspect there's a bug in X\", \"something is wrong with this contract\", or when reasoning about whether a Move function can be abused.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1023,1026,1029,1032],{"name":1024,"slug":1025,"type":15},"Code Review","code-review",{"name":1027,"slug":1028,"type":15},"Security","security",{"name":1030,"slug":1031,"type":15},"Smart Contracts","smart-contracts",{"name":14,"slug":8,"type":15},"2026-07-16T06:02:55.691149",{"slug":1035,"name":1035,"fn":1036,"description":1037,"org":1038,"tags":1039,"stars":1049,"repoUrl":1050,"updatedAt":1051},"memwal","integrate Walrus Memory SDK","Walrus Memory SDK — portable agent memory that works across apps, sessions, and workflows.\n\nUse when users say:\n- \"add memory to my app\"\n- \"portable agent memory\"\n- \"integrate Walrus Memory\"\n- \"AI agent memory\"\n- \"memory across agents\"\n- \"Walrus memory storage\"\n- \"setup Walrus Memory\"\n- \"recall memories\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1040,1043,1046],{"name":1041,"slug":1042,"type":15},"Agents","agents",{"name":1044,"slug":1045,"type":15},"Memory","memory",{"name":1047,"slug":1048,"type":15},"SDK","sdk",57,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002FMemWal","2026-07-16T06:02:39.838395",{"slug":1053,"name":1053,"fn":1054,"description":1055,"org":1056,"tags":1057,"stars":25,"repoUrl":26,"updatedAt":1063},"accessing-data","read data from the Sui network","How to read data from the Sui network. Use when choosing or implementing a data access strategy — queries for on-chain state, indexing pipelines, historical lookups, event subscriptions, cross-chain reads, or off-chain blob storage. Covers the two live Sui APIs (gRPC and GraphQL RPC), the Archival Store, the General-Purpose Indexer, the `sui-indexer-alt` custom indexing framework, and Walrus for off-chain blobs.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1058,1061,1062],{"name":1059,"slug":1060,"type":15},"Data Analysis","data-analysis",{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-08-01T05:44:32.775598",{"slug":1065,"name":1065,"fn":1066,"description":1067,"org":1068,"tags":1069,"stars":25,"repoUrl":26,"updatedAt":1076},"composable-move-functions","design composable Sui Move functions","Use when writing Move functions on Sui, especially public APIs. Applies to function visibility (public vs entry), parameter ordering, and return patterns. Use whenever designing function signatures or deciding whether functions should transfer objects or return them.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1070,1073,1074,1075],{"name":1071,"slug":1072,"type":15},"API Development","api-development",{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:49.198495",{"slug":1078,"name":1078,"fn":1079,"description":1080,"org":1081,"tags":1082,"stars":25,"repoUrl":26,"updatedAt":1095},"frontend-apps","build Sui dApps with dapp-kit","Sui frontend \u002F dApp development with @mysten\u002Fdapp-kit-react (React) and @mysten\u002Fdapp-kit-core (Vue, vanilla JS, Svelte, Web Components, other frameworks). Use when building browser apps that connect Sui wallets, query on-chain state, or submit transactions. Covers wallet connection, network switching, transaction execution, query patterns with TanStack React Query, and the specific pitfalls of browser + wallet + async-indexer environments. Pair with the `sui-sdks` skill for @mysten\u002Fsui Transaction construction patterns and the `ptbs` skill for PTB semantics.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1083,1084,1087,1088,1091,1094],{"name":23,"slug":24,"type":15},{"name":1085,"slug":1086,"type":15},"React","react",{"name":14,"slug":8,"type":15},{"name":1089,"slug":1090,"type":15},"Svelte","svelte",{"name":1092,"slug":1093,"type":15},"Vue","vue",{"name":17,"slug":18,"type":15},"2026-08-01T05:44:28.958473",{"slug":1097,"name":1097,"fn":1098,"description":1099,"org":1100,"tags":1101,"stars":25,"repoUrl":26,"updatedAt":1107},"generate-sui-agent-config","generate configuration files for Sui projects","Generate a CLAUDE.md or AGENT.md configuration file for Sui projects. Use when setting up a new Sui project, when user mentions \"CLAUDE.md\", \"AGENT.md\", \"agent config\", or when working on a Sui project that does not already have a CLAUDE.md or AGENT.md in the project root.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1102,1105,1106],{"name":1103,"slug":1104,"type":15},"Configuration","configuration",{"name":1003,"slug":1004,"type":15},{"name":14,"slug":8,"type":15},"2026-07-16T06:00:59.981056",{"slug":1109,"name":1109,"fn":1110,"description":1111,"org":1112,"tags":1113,"stars":25,"repoUrl":26,"updatedAt":1118},"modern-move-syntax","write Move 2024 edition code for Sui","Use when writing Move code on Sui to ensure 2024 edition syntax is used. Applies to method calls, string literals, vector operations, option handling, loops, and struct unpacking. Use whenever writing Move code to avoid legacy function-call syntax patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1114,1115,1116,1117],{"name":990,"slug":991,"type":15},{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:43.277596",{"slug":1120,"name":1120,"fn":1121,"description":1122,"org":1123,"tags":1124,"stars":25,"repoUrl":26,"updatedAt":1134},"move-unit-testing","write unit tests for Sui Move contracts","Use when writing unit tests for Move smart contracts on Sui. Applies to test function naming, assertions, test attributes, context usage, and cleanup patterns. Use whenever user asks to write tests, add tests, or test a Move module.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1125,1128,1129,1130,1133],{"name":1126,"slug":1127,"type":15},"QA","qa",{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":1131,"slug":1132,"type":15},"Testing","testing",{"name":17,"slug":18,"type":15},"2026-08-01T05:44:30.788585",{"slug":1136,"name":1136,"fn":1137,"description":1138,"org":1139,"tags":1140,"stars":25,"repoUrl":26,"updatedAt":1147},"naming-conventions","apply Sui Move naming conventions","Use when writing or reviewing Move smart contracts on Sui. Applies to naming structs, error constants, regular constants, events, getter functions, capability types, hot potato types, and dynamic field keys. Use whenever creating new types, functions, or constants in Move code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1141,1144,1145,1146],{"name":1142,"slug":1143,"type":15},"Best Practices","best-practices",{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:48.830052",37,{"items":1150,"total":1201},[1151,1157,1164,1173,1179,1186,1194],{"slug":1053,"name":1053,"fn":1054,"description":1055,"org":1152,"tags":1153,"stars":25,"repoUrl":26,"updatedAt":1063},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1154,1155,1156],{"name":1059,"slug":1060,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":1065,"name":1065,"fn":1066,"description":1067,"org":1158,"tags":1159,"stars":25,"repoUrl":26,"updatedAt":1076},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1160,1161,1162,1163],{"name":1071,"slug":1072,"type":15},{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":1078,"name":1078,"fn":1079,"description":1080,"org":1165,"tags":1166,"stars":25,"repoUrl":26,"updatedAt":1095},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1167,1168,1169,1170,1171,1172],{"name":23,"slug":24,"type":15},{"name":1085,"slug":1086,"type":15},{"name":14,"slug":8,"type":15},{"name":1089,"slug":1090,"type":15},{"name":1092,"slug":1093,"type":15},{"name":17,"slug":18,"type":15},{"slug":1097,"name":1097,"fn":1098,"description":1099,"org":1174,"tags":1175,"stars":25,"repoUrl":26,"updatedAt":1107},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1176,1177,1178],{"name":1103,"slug":1104,"type":15},{"name":1003,"slug":1004,"type":15},{"name":14,"slug":8,"type":15},{"slug":1109,"name":1109,"fn":1110,"description":1111,"org":1180,"tags":1181,"stars":25,"repoUrl":26,"updatedAt":1118},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1182,1183,1184,1185],{"name":990,"slug":991,"type":15},{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":1120,"name":1120,"fn":1121,"description":1122,"org":1187,"tags":1188,"stars":25,"repoUrl":26,"updatedAt":1134},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1189,1190,1191,1192,1193],{"name":1126,"slug":1127,"type":15},{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":1131,"slug":1132,"type":15},{"name":17,"slug":18,"type":15},{"slug":1136,"name":1136,"fn":1137,"description":1138,"org":1195,"tags":1196,"stars":25,"repoUrl":26,"updatedAt":1147},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1197,1198,1199,1200],{"name":1142,"slug":1143,"type":15},{"name":1030,"slug":1031,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},20]