An IPFS website starts with an ordinary publishing question: which files should a visitor receive? Before thinking about wallets, tokens, or distributed infrastructure, assemble a complete website that works as a folder. HTML provides the pages, CSS provides the presentation, and a small amount of JavaScript can provide navigation. The useful change is how that folder is addressed and retrieved, not a requirement to replace familiar web development.

This guide follows a small documentation site through its first release. The aim is not to promise that a successful upload makes a website permanent. The aim is to produce a release you can identify, keep available, test independently, and replace deliberately. For the underlying vocabulary, start with our IPFS website overview.

1. Define a static release

A static release contains the files that a server or gateway sends directly to a browser. It does not need a running application process to generate each page. If your project currently depends on server rendering, a database query at request time, or a server-only login handler, exporting the source repository is not enough. You need an actual static build, and any remaining external services must be documented separately.

Write a small acceptance statement before building: a visitor can open the homepage, navigate to the guide, view the images, and find the contact details with no account. That statement keeps your first release focused. A site with three finished pages is a better test than a large shell full of buttons that have no destination.

2. Give every page a real directory

Use a folder layout with an entry document at each route. Your homepage lives in the root; the guide has its own directory; images and styles have predictable locations. For example:

site/
  index.html
  guides/
    index.html
  about/
    index.html
  assets/
    style.css
    network.png

The public links can be guides/ and about/, without HTML extensions. A directory-based site avoids assuming that a gateway will apply your old server's rewrite rules. It also makes failures easier to investigate: a missing guide is a missing file, not a mystery involving application routing.

Keep the deployment directory separate from your working repository. Never publish environment files, private drafts, access tokens, or source maps containing sensitive material simply because they sit beside your application code.

A link beginning with a slash starts at the host's root. That is convenient on a conventional domain but can escape a website mounted beneath a gateway path. A page under an IPFS content path may need a relative link that stays inside its release directory. From a nested guide, the stylesheet could be referenced as ../assets/style.css.

Do not fix only the navigation. Inspect image sources, CSS background images, JavaScript imports, downloadable files, and dynamically constructed links. Test a nested page directly rather than reaching it only from the homepage. A root page can look perfect while every deep link is broken.

Canonical URLs serve a different purpose from browsing links. You can retain a preferred branded HTTPS address in search metadata while making the actual page-to-page links portable. See the static website guide for this separation.

4. Build, then inspect the actual output

Run your normal production build before adding anything to IPFS. Compile your stylesheet locally rather than depending on a development-only styling script in the browser. Remove unused sample images, temporary downloads, and development dependencies from the output folder. Check that the release does not fetch its entire visual identity from an unrelated third-party asset server.

Open the output through a local HTTP server. Double-clicking files is not an equivalent test of directory routing or browser security behavior. Inspect the browser's network panel for missing resources, unexpected remote requests, and development URLs. Try the menu with a keyboard, increase text size, and use a narrow viewport. These are ordinary website checks that become especially valuable before publishing a content-addressed release.

5. Add the directory and record its address

With Kubo installed and initialized, a typical local command for a directory is:

ipfs add -r --cid-version=1 ./site

The output contains identifiers for individual files and the containing directory. Record the directory's CID, not just the identifier of the homepage file. The directory is what preserves the relationships among pages and assets. For the reference workflow and directory behavior, consult the official IPFS multi-page website tutorial.

Treat the result as a release artifact. Save the source revision, build command, tool versions, and resulting root CID together in your own release notes. Do not hand-edit the published folder afterward and assume the record still describes it. A changed build needs its own recorded identity.

6. Make availability an explicit task

An address is not an availability contract. Arrange for the directory and its reachable content to remain pinned on infrastructure that will stay online. You might operate your own node, use a pinning provider, or combine independent copies. Whichever arrangement you choose, record who is responsible for retaining it and how you will notice a failure.

Do not confuse a browser cache with durable hosting. A cached page may continue opening on your laptop while a new visitor cannot retrieve it. Test from a separate environment that has not just uploaded the files. For a more complete operational plan, read how IPFS hosting and pinning fit together.

7. Verify the release as a visitor

Open the root through your intended delivery route. Then open a nested page in a new tab, reload it, and follow links back to the homepage. Confirm that a deliberately nonexistent route fails rather than silently showing unrelated content. Check image dimensions and inspect the console for missing modules or blocked requests.

Hand the release to another reader

Use a second retrieval route as a diagnostic comparison, not as proof of universal availability. One gateway may have a warm cache, while another is doing a fresh lookup. If retrieval differs, investigate the provider and delivery paths separately. Keep the exact URL, time, and error message; those details are more useful than a report that the website is simply down.

8. Publish a name only after testing

A readable name makes a site easier to share, but it should point to a release that has already passed inspection. Plan your custom domain and HTTPS delivery independently from the content's CID. Update the naming layer only after the new release is available. Keep the previous working release until your rollback window has passed.

When a deployment breaks, a useful rollback restores both the intended pointer and the files required by that release. Saving an old CID is not enough if its content is no longer retained. Our DNSLink and gateway guide walks through that operational boundary.

A practical first-release checklist

Before calling the release finished, ask someone who did not build it to use it. Give that person a direct link to a nested page. Ask them to find the homepage, open an image, locate contact details, and navigate without a mouse. Watch for assumptions you no longer notice because you know the site so well.

Write down the expected outcomes and the actual results. A small checklist becomes a reusable release test rather than a one-time memory. Include the root CID, the location of retained copies, the canonical domain, and the previous release. Keep private deployment credentials out of that public checklist.

Conclusion: publish a release, not just an upload

Your first IPFS static website is successful when its files are complete, its links are portable, its content can be retrieved, and its next update has a clear path. None of those tasks requires a token or an elaborate application stack. Begin with a small static folder, verify its directory CID, and give availability an owner. That approach creates a foundation you can later extend with Hugo, a CMS, or a carefully designed dApp frontend.