A celebration of life website: one page guests can open without an account

Family and friends need the time, the place and somewhere to read the stories. That fits on one page, and one page is a single file you can share as a link.

A celebration of life website can be one page: the name, the day and time, the place, and the stories people want to read.

People ask which free or cheap builder suits a simple one-page site. Here you can skip it: an AI chat writes the page, and NOS turns it into a link.

Guests may be older, far away, or reading on a phone in a hurry. A link they open without signing up suits them. Here is a finished page to copy.

Live exampletry it here, then copy the code
Share it as a link
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Celebrating the life of Peggy Hollis</title>
<style>
  * { box-sizing: border-box; }
  body { margin: 0; background: #f6f3ee; color: #2b2a28; font-family: Georgia, "Times New Roman", serif; line-height: 1.6; font-size: 1.05rem; }
  .wrap { max-width: 560px; margin: 0 auto; padding: 0 18px 40px; }
  header { text-align: center; padding: 36px 0 18px; }
  header svg { width: 72px; height: 72px; }
  .kicker { margin: 8px 0 0; font: 700 .76rem system-ui, sans-serif; letter-spacing: 1.6px; text-transform: uppercase; color: #5f7a5a; }
  h1 { font-size: 2.1rem; font-weight: 400; margin: 4px 0 2px; }
  .years { margin: 0; color: #6d6a64; font-style: italic; }
  .when { margin: 16px 0 2px; font-size: 1.25rem; }
  .count { margin: 0; font: 600 .86rem system-ui, sans-serif; color: #5f7a5a; }
  section { background: #fff; border-radius: 12px; padding: 16px 18px; margin-top: 14px; box-shadow: 0 1px 4px rgba(40, 40, 30, .08); }
  h2 { font: 700 .78rem system-ui, sans-serif; letter-spacing: 1.4px; text-transform: uppercase; color: #5f7a5a; margin: 0 0 8px; }
  .venue { font-size: 1.15rem; margin: 0; }
  .addr { margin: 2px 0 12px; color: #6d6a64; }
  .btn { display: inline-block; padding: 12px 18px; border-radius: 8px; background: #4d6a49; color: #fff; text-decoration: none; font: 600 .98rem system-ui, sans-serif; }
  ul.times { list-style: none; margin: 0; padding: 0; }
  ul.times li { display: flex; gap: 14px; padding: 7px 0; border-top: 1px solid #ece8e0; }
  ul.times li:first-child { border-top: 0; }
  ul.times b { flex: 0 0 76px; font: 700 .95rem system-ui, sans-serif; }
  blockquote { margin: 0; padding: 10px 0 10px 14px; border-left: 3px solid #b9c9b5; }
  blockquote + blockquote { margin-top: 10px; }
  blockquote p { margin: 0 0 4px; }
  cite { font: 600 .88rem system-ui, sans-serif; color: #6d6a64; font-style: normal; }
  .ask { margin: 12px 0 0; color: #6d6a64; font-size: .95rem; }
  details { border-top: 1px solid #ece8e0; padding: 9px 0; }
  details:first-of-type { border-top: 0; }
  summary { cursor: pointer; font-weight: 700; }
  details p { margin: 6px 0 0; color: #4a4843; }
  footer { text-align: center; margin-top: 22px; color: #6d6a64; font-size: .95rem; }
</style>
</head>
<body>
<div class="wrap">

  <header>
    <svg viewBox="0 0 72 72" aria-hidden="true">
      <circle cx="36" cy="36" r="34" fill="#e4ebe1"/>
      <path d="M36 54 C36 40 36 32 36 20" stroke="#4d6a49" stroke-width="3" fill="none" stroke-linecap="round"/>
      <path d="M36 44 C26 44 20 38 20 30 C30 30 36 36 36 44Z" fill="#7d9b78"/>
      <path d="M36 36 C46 36 52 30 52 22 C42 22 36 28 36 36Z" fill="#9db898"/>
    </svg>
    <p class="kicker">A celebration of life</p>
    <h1>Peggy Hollis</h1>
    <p class="years">1941 &ndash; 2026</p>
    <p class="when"><time datetime="2026-11-14T14:00">Saturday 14 November 2026, 2:00 pm</time></p>
    <p class="count" id="count"></p>
  </header>

  <section>
    <h2>Where</h2>
    <p class="venue">Ashby Green Village Hall</p>
    <p class="addr">12 Meadow Lane, Ashby Green</p>
    <a class="btn" href="https://www.google.com/maps/search/?api=1&amp;query=Ashby+Green+Village+Hall+12+Meadow+Lane" target="_blank" rel="noopener">Open in maps</a>
  </section>

  <section>
    <h2>The afternoon</h2>
    <ul class="times">
      <li><b>2:00 pm</b> Welcome and a song</li>
      <li><b>2:15 pm</b> Words from the family</li>
      <li><b>2:45 pm</b> Stories from anyone who would like to share one</li>
      <li><b>3:30 pm</b> Tea, sandwiches and Peggy&rsquo;s lemon cake</li>
      <li><b>4:30 pm</b> Close</li>
    </ul>
  </section>

  <section>
    <h2>Stories</h2>
    <blockquote>
      <p>She kept a jar of toffees by the door and always said they were for the postman. The postman never got one.</p>
      <cite>Marcus, neighbour</cite>
    </blockquote>
    <blockquote>
      <p>Peggy taught me to drive in a hall car park on Sundays. She never once raised her voice, only her eyebrows.</p>
      <cite>Eleni, granddaughter</cite>
    </blockquote>
    <p class="ask">Have a story? Message Dan before 11 November and he will add it here.</p>
  </section>

  <section>
    <h2>Good to know</h2>
    <details open>
      <summary>What to wear</summary>
      <p>Peggy loved colour. Wear something bright if you like. Black is not required.</p>
    </details>
    <details>
      <summary>Flowers</summary>
      <p>The family asks for no flowers. A donation to the Ashby Green Garden Club would please her.</p>
    </details>
    <details>
      <summary>Parking and access</summary>
      <p>Parking is behind the hall. The entrance is step-free, and there are seats at the front.</p>
    </details>
    <details>
      <summary>Children</summary>
      <p>Children are very welcome.</p>
    </details>
  </section>

  <footer>With love, from Dan, Eleni and the family.</footer>
</div>

<script>
  // Days left until the day (dates in this example are made up)
  const day = new Date(2026, 10, 14);
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const left = Math.round((day - today) / 86400000);
  const el = document.getElementById('count');
  el.textContent = left > 1 ? left + ' days to go' : left === 1 ? 'Tomorrow' : left === 0 ? 'Today' : 'Thank you for coming';
</script>
</body>
</html>
A complete one-page site with time, place, order of the afternoon, stories and notes. Scroll inside the example, or edit the code.

The names, hall and times are made up. Swap in yours. The line under the date is a small script that counts days, and it runs on the shared link too.

What goes on the page

Most guests will open the link on a phone, so the page is one column, and the answer to "when and where" sits on the first screen.

The page on a phone, top to bottom, with what each block is for.
The page on a phone, top to bottom, with what each block is for.

Four blocks cover it: the name and time, the place with a map button, the stories, and a few notes. The time sits in an HTML time element, which MDN describes as a way to give a date in a form machines can read.

The notes use the native details element. It shows a heading that opens and closes the text under it, and MDN documents that it needs no JavaScript. Dress, flowers, parking and children each get a heading.

For a page built around one event, see event landing page.

Make it with AI

Paste this prompt into ChatGPT, Claude or Gemini after replacing the details in capitals.

Write one self-contained HTML file for a celebration of life page.
In memory of: FULL NAME, YEARS. Host: NAME, relationship.
Date: DAY, DATE, YEAR, TIME. Venue: NAME, FULL ADDRESS.
Order of the afternoon: TIME - WHAT HAPPENS (one line each).
Stories: paste 2-3 short ones with who sent each.
Notes: what to wear, flowers or donations, parking, children.
Tone: calm, warm, plain. One column, readable on a phone, with the
viewport meta tag. Put the date and time at the top. Under the venue,
add a button that links to a Google Maps search URL for the address.
Show notes with details and summary. No external images, no iframes,
no libraries. Decorate with CSS or inline SVG only. Return only the code.

Then check the result yourself. An AI can change a fact without any sign.

  • The name is spelled exactly as the family writes it.
  • The day of the week matches the date.
  • Every time and the address are as you wrote them.
  • The map button opens the right place when you tap it.
  • Each story is word for word what its author sent, with the right name.
  • No placeholder text such as "Your venue here" is left.

Paste the finished code into a NOS document and choose Create share link. The page renders as written, scripts included. HTML to link walks through it.

From the AI chat to a link guests can open.
From the AI chat to a link guests can open.

Anyone with the link opens the page in a browser, on a phone too, with no account. They cannot edit it. When a time changes, edit the code and the same link shows the new version.

A file is a copy, and a picture of the invitation is a copy too. A link is the page itself. Why a file often fails on a phone is in opening an HTML file on a phone.

Think before you post the link in a public place. NOS has no password, so anyone who gets the link can read the page. Leave off a private home address and say where to find that in a message instead.

To print the link on the order of service, turn it into a QR code. QR code link shows how.

Ways to share the details compared

Way Guest opens it A change reaches guests
Printed notice only On paper Only by contacting people
Picture in a chat In the chat Only if you send a new one
HTML file as attachment Depends on the phone and the app Only if you send it again
NOS share link In the browser, no account Yes, the same link updates
Google Sites page In the browser, once published See Google's help

Google Sites is a separate tool with its own editor. As of October 2026, Google's help says you publish a site with a web address and choose whether it is restricted to people you invite or public.

The map button uses a search URL that Google documents. It needs no API key, and on Android and iOS it opens the Maps app when that is installed and a browser when it is not.

Stories guests send you

A page for reading is also a page for remembering. Guests cannot type on it, so they send you a story and you place it on the page.

How a story travels from a guest to the page, with the link staying the same.
How a story travels from a guest to the page, with the link staying the same.

Here is a page that holds stories only. Filter by who wrote them, read one at random, or make the text larger for readers who want it.

Live exampletry it here, then copy the code
Share it as a link
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Stories about Peggy</title>
<style>
  * { box-sizing: border-box; }
  body { margin: 0; padding: 16px; background: #f6f3ee; color: #2b2a28; font-family: Georgia, "Times New Roman", serif; line-height: 1.55; }
  .wrap { max-width: 560px; margin: 0 auto; }
  h1 { font-size: 1.5rem; font-weight: 400; margin: 0 0 2px; }
  .sub { margin: 0 0 14px; color: #6d6a64; font-style: italic; }
  .bar { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
  button { font: 600 .9rem system-ui, sans-serif; padding: 10px 14px; border-radius: 8px; border: 1px solid #b9c9b5; background: #fff; color: #3f5a3b; cursor: pointer; }
  button[aria-pressed="true"] { background: #4d6a49; color: #fff; border-color: #4d6a49; }
  .tools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
  #stories { font-size: 1.05rem; }
  article { background: #fff; border-radius: 12px; padding: 14px 16px; margin-bottom: 10px; box-shadow: 0 1px 4px rgba(40, 40, 30, .08); border: 2px solid transparent; }
  article[hidden] { display: none; }
  article.pick { border-color: #7d9b78; }
  article p { margin: 0 0 6px; }
  cite { font: 600 .88rem system-ui, sans-serif; font-style: normal; color: #6d6a64; }
  .none { color: #6d6a64; }
</style>
</head>
<body>
<div class="wrap">
  <h1>Stories about Peggy</h1>
  <p class="sub">Sent in by family, friends and neighbours.</p>

  <div class="bar" id="filters">
    <button data-group="all" aria-pressed="true">All</button>
    <button data-group="family" aria-pressed="false">Family</button>
    <button data-group="friends" aria-pressed="false">Friends</button>
    <button data-group="neighbours" aria-pressed="false">Neighbours</button>
  </div>
  <div class="tools">
    <button id="random">Read one at random</button>
    <button id="big" aria-pressed="false">Larger text</button>
  </div>

  <div id="stories">
    <article data-group="neighbours"><p>She kept a jar of toffees by the door and always said they were for the postman. The postman never got one.</p><cite>Marcus, neighbour</cite></article>
    <article data-group="family"><p>Peggy taught me to drive in a hall car park on Sundays. She never once raised her voice, only her eyebrows.</p><cite>Eleni, granddaughter</cite></article>
    <article data-group="friends"><p>Every spring she gave away seedlings from her windowsill. Half the gardens on our road began in her kitchen.</p><cite>Roz, friend from the garden club</cite></article>
    <article data-group="family"><p>She answered the phone with the full number, even for family. We still do it as a joke.</p><cite>Dan, son</cite></article>
    <article data-group="friends"><p>She beat me at cards for thirty years and never once let me forget it. I would give anything for one more hand.</p><cite>Walter, friend</cite></article>
    <article data-group="neighbours"><p>When our power went out, she appeared with a flask of soup and a torch and stayed to play board games.</p><cite>The Okafor family, next door</cite></article>
    <p class="none" id="none" hidden>No stories in this group yet.</p>
  </div>
</div>

<script>
  const items = [...document.querySelectorAll('#stories article')];
  const filters = [...document.querySelectorAll('#filters button')];
  const none = document.getElementById('none');
  const big = document.getElementById('big');

  function show(group) {
    // Show one group, or all of them
    items.forEach((a) => {
      a.classList.remove('pick');
      a.hidden = group !== 'all' && a.dataset.group !== group;
    });
    filters.forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.group === group)));
    none.hidden = items.some((a) => !a.hidden);
  }

  filters.forEach((b) => b.addEventListener('click', () => show(b.dataset.group)));

  document.getElementById('random').addEventListener('click', () => {
    show('all');
    const a = items[Math.floor(Math.random() * items.length)];
    items.forEach((x) => x.classList.toggle('pick', x === a));
    a.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
  });

  big.addEventListener('click', () => {
    const on = big.getAttribute('aria-pressed') !== 'true';
    big.setAttribute('aria-pressed', String(on));
    document.getElementById('stories').style.fontSize = on ? '1.35rem' : '1.05rem';
  });
</script>
</body>
</html>
Filter the stories, press the random button, or switch to larger text. Each story is one block of code you can copy.

Each story is one block with its text and a name. Ask the AI to add a story in the same style, and read it before you save. For sending the page out in the first place, see invitation to link.

When it does not work

What you see Cause Fix
The page looks tiny on a phone The viewport meta tag is missing Ask the AI to add it, see viewport meta tag
A photo is missing The image is hosted on another site, which NOS blocks Use CSS or inline SVG
The map area is empty An embedded map uses an iframe, which NOS blocks Replace it with a button that links to the map
A guest cannot add a story A visitor's changes are not saved, and forms cannot send to a server Ask guests to message you
A guest still sees the old time They have the old page open Ask them to reload the link
The AI changed a name or a date Generated text can drift from your input Read every fact before sharing

Questions people ask

Do I need a website builder for a celebration of life website?

No. The page is one HTML file. An AI chat can write it from your details, and you paste it into NOS to get a link. A builder is one way to get a page, not a requirement.

Do guests need to sign up to read it?

No. A NOS share link opens in a browser, on a phone too, with no account. Guests can read the page but cannot edit it.

Can guests post their own stories on the page?

Not directly. A visitor cannot change the page, and sending a form to a server is blocked in NOS. Ask guests to message you, then add their story to the code yourself.

Can I make the page private?

NOS has no password option. Anyone who has the link can open the page, and a link in a group chat can be forwarded. Leave out anything you would not want a stranger to read, such as the home address.

What if the time or the place changes?

Edit the code in NOS. The share link stays the same, so people who open it afterwards see the new version. A guest who already has the page open needs to reload it.

Keep reading