How to make a celebration of life program you can share and correct

One page can hold the order of service, and one link can carry it to everyone before the day. When a time changes, you fix the page and the link stays the same.

A celebration of life program is the order of the service: times, who speaks, the music, and where to go afterwards. You do not need a site builder for it. Ask an AI chat for one page and send it as a link.

Times and names sometimes change in the last days. A printed or attached copy cannot follow the change. A link shows whatever the page says now. Here is a program of that kind, with a made-up person and place.

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>Celebration of life for Joan Aldersey</title>
<style>
  * { box-sizing: border-box; }
  body {
    margin: 0; font-family: Georgia, "Times New Roman", serif; font-size: 17px;
    background: #f7f4ee; color: #2b2a28; line-height: 1.55;
  }
  body.big { font-size: 21px; }
  .wrap { max-width: 640px; margin: 0 auto; padding: 24px 16px 36px; }
  header { text-align: center; padding-bottom: 14px; border-bottom: 1px solid #d9d1c5; }
  .emblem { width: 72px; height: 72px; display: block; margin: 0 auto 8px; }
  h1 { font-size: 1.7em; margin: 0; font-weight: 600; line-height: 1.2; }
  .sub { margin: 4px 0 0; color: #5d564a; }
  .when { margin: 10px 0 0; font-weight: 600; color: #4b3f2f; }
  .notice { margin: 16px 0 0; padding: 10px 14px; background: #fff7e0; border-left: 4px solid #c9962b; border-radius: 6px; font-size: .92em; }
  .tools { text-align: right; margin: 14px 0 4px; }
  .tools button {
    font: inherit; font-size: .85em; padding: 6px 12px; border-radius: 8px; cursor: pointer;
    background: #fff; border: 1px solid #b9ad98; color: #3d372d;
  }
  .tools button[aria-pressed="true"] { background: #4b3f2f; color: #fff; border-color: #4b3f2f; }
  h2 { font-size: 1.15em; margin: 22px 0 8px; color: #4b3f2f; }
  ol.order { list-style: none; margin: 0; padding: 0; }
  ol.order li {
    display: grid; grid-template-columns: 5.2em 1fr; gap: 4px 12px;
    padding: 11px 0; border-bottom: 1px solid #e3dccf;
  }
  ol.order time { font-weight: 700; color: #7a5c20; font-variant-numeric: tabular-nums; }
  ol.order .what { font-weight: 600; }
  ol.order .who { display: block; color: #5d564a; font-weight: 400; font-size: .92em; }
  details { margin-top: 6px; font-size: .92em; }
  summary { cursor: pointer; color: #6b4e12; }
  details p { margin: 6px 0 0; padding: 8px 12px; background: #fff; border-radius: 8px; }
  .card { background: #fff; border-radius: 12px; padding: 12px 16px; box-shadow: 0 2px 8px rgba(0,0,0,.06); }
  .card p { margin: 0 0 6px; }
  .card p:last-child { margin: 0; }
  footer { margin-top: 24px; text-align: center; color: #5d564a; font-size: .85em; }
</style>
</head>
<body>
<div class="wrap">
  <header>
    <svg class="emblem" viewBox="0 0 72 72" role="img" aria-label="A simple sprig of leaves">
      <circle cx="36" cy="36" r="34" fill="#ece3d1"/>
      <path d="M36 58V24" stroke="#6f8a58" stroke-width="3" stroke-linecap="round"/>
      <path d="M36 44c-10 0-14-6-14-12 8 0 14 4 14 12z" fill="#8fb078"/>
      <path d="M36 34c10 0 14-6 14-12-8 0-14 4-14 12z" fill="#8fb078"/>
      <path d="M36 24c-5-3-6-9-4-13 5 2 7 8 4 13z" fill="#a8c490"/>
    </svg>
    <h1>A celebration of the life of Joan Aldersey</h1>
    <p class="sub"><time datetime="1948-04-03">3 April 1948</time> &ndash; <time datetime="2026-09-20">20 September 2026</time></p>
    <p class="when"><time datetime="2026-10-17T14:00">Saturday 17 October 2026, 2:00 pm</time><br>Fernhill Garden Hall (a made-up place for this example)</p>
    <p class="notice"><b>Updated 1 October:</b> open sharing now starts at 2:35 pm. The photographs follow it.</p>
  </header>

  <div class="tools"><button type="button" id="size" aria-pressed="false">Larger text</button></div>

  <h2>Order of service</h2>
  <ol class="order">
    <li><time datetime="14:00">2:00 pm</time><div><span class="what">Gathering music</span><span class="who">Piano, played by Rosa Trent</span></div></li>
    <li><time datetime="14:10">2:10 pm</time><div><span class="what">Welcome</span><span class="who">Daniel Aldersey, her son</span></div></li>
    <li><time datetime="14:15">2:15 pm</time><div><span class="what">A reading</span><span class="who">Priya Nair, a friend</span>
      <details><summary>Read the words</summary><p>A short poem chosen by the family. Its words are printed here so everyone can follow along.</p></details></div></li>
    <li><time datetime="14:20">2:20 pm</time><div><span class="what">Remembering Joan</span><span class="who">Margaret Hale, her sister</span></div></li>
    <li><time datetime="14:30">2:30 pm</time><div><span class="what">A song she loved</span><span class="who">Recorded, all welcome to sing</span></div></li>
    <li><time datetime="14:35">2:35 pm</time><div><span class="what">Open sharing</span><span class="who">Anyone who would like to say a few words</span></div></li>
    <li><time datetime="14:55">2:55 pm</time><div><span class="what">Photographs</span><span class="who">A slideshow of her garden years</span></div></li>
    <li><time datetime="15:00">3:00 pm</time><div><span class="what">Closing words</span><span class="who">Daniel Aldersey</span></div></li>
    <li><time datetime="15:05">3:05 pm</time><div><span class="what">Tea, cake and conversation</span><span class="who">In the hall, everyone welcome</span></div></li>
  </ol>

  <h2>Good to know</h2>
  <div class="card">
    <p><b>Please wear:</b> something colourful. Joan liked colour.</p>
    <p><b>Step-free access:</b> the main door has a ramp.</p>
    <p><b>Questions:</b> reply to the message that brought you this page.</p>
  </div>

  <footer>This page shows the current order. If a time changes, this same link shows the new one.</footer>
</div>

<script>
  // Toggle a larger text size for easier reading
  const btn = document.getElementById('size');
  btn.addEventListener('click', () => {
    const on = document.body.classList.toggle('big');
    btn.setAttribute('aria-pressed', on);
    btn.textContent = on ? 'Normal text' : 'Larger text';
  });
</script>
</body>
</html>
A one-page order of service with a change note, an expandable reading and a larger-text button. All names and places are made up.

What goes in a celebration of life program

People open it on a phone, often from a message, and look for the same few things. Put those first.

  • Date, time and place. At the top, before anything else.
  • The order of service. One line per item: the time, what it is, and who does it.
  • Words people may want to follow. A reading or the title of a song.
  • Practical details. What to wear, access to the building, and what happens afterwards.
  • Where to ask. One sentence saying who to reply to.

Ask each person named on the page whether they are happy to be named, and whether the time suits them.

Make it with AI

An AI chat such as ChatGPT, Claude or Gemini can write the page from your list. Paste this prompt, then replace the bracketed parts.

Write one complete HTML page, in a single file, as the order of service
for a celebration of life. Use a calm, light layout with large text.
It must work on a phone. Do not load anything from other websites:
no external images, scripts or fonts.
Use only the facts I give you. Do not invent times, names, readings or quotes.
Put the date, time and place at the top, then a notice line I can edit,
then the order of service as a list with one line per item,
then practical details, then where to send a question.
Draw any picture as a simple inline SVG.

Name: [name]
Dates: [born] to [died]
When and where: [date, time, place]
Order: [time, item, who] one item per line
Practical: [what to wear, access, afterwards]
Questions to: [for example "reply to the message you received"]

When the page comes back, check these before anything else:

  • Every time matches your list, and the order is the one you meant.
  • Every name is spelled the way the person spells it.
  • No reading, quote or detail appears that you did not provide.
  • The page reads well when you shrink the browser window to phone width.

If something is wrong, tell the chat the correction in plain words, then copy the new version. Host ChatGPT HTML output covers the copy step.

Copy the HTML from the chat, paste it into a NOS document, and choose Create share link. HTML to link walks through it. The page renders as written.

The people you send it to open it in a browser, phone included, with no account. They cannot edit it.

From your list to a link in four steps.
From your list to a link in four steps.

Open the link on your own phone before you send it. Check the date and place at the top, then scroll down to the end.

What a guest sees on a phone, and why the page is laid out that way.
What a guest sees on a phone, and why the page is laid out that way.

For a printed sheet at the venue, a QR code can point to the same link. QR code link explains how. Event landing page covers a page that also holds directions and parking.

Correct it after you have sent it

When a time moves, every later time moves with it. Work that out first, then change the page once.

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>Timing sheet</title>
<style>
  * { box-sizing: border-box; }
  body { margin: 0; font-family: system-ui, "Segoe UI", sans-serif; font-size: 16px; background: #f4f6f8; color: #1f2933; line-height: 1.45; }
  .wrap { max-width: 640px; margin: 0 auto; padding: 18px 14px 30px; }
  h1 { font-size: 20px; margin: 0 0 4px; }
  p.hint { margin: 0 0 14px; color: #52606d; font-size: 14px; }
  .start { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
  input[type="time"], input[type="number"], input[type="text"] {
    font: inherit; padding: 7px 8px; border: 1px solid #b8c2cc; border-radius: 8px; background: #fff; min-width: 0;
  }
  table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,.08); }
  th { text-align: left; font-size: 13px; color: #52606d; padding: 8px 10px; background: #e9eef3; }
  td { padding: 6px 10px; border-top: 1px solid #e5eaef; vertical-align: middle; }
  td.t { font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; color: #7a4a05; width: 5.5em; }
  td.m { width: 6em; }
  td.m input { width: 100%; }
  td.x { width: 2.4em; text-align: right; }
  td.x button { border: 0; background: none; font-size: 18px; color: #7b8794; cursor: pointer; padding: 2px 6px; }
  .add { display: flex; gap: 8px; margin: 12px 0; }
  .add input[type="text"] { flex: 1; }
  button.go { font: inherit; padding: 7px 14px; border: 0; border-radius: 8px; background: #2f5d8a; color: #fff; cursor: pointer; }
  .sum { margin: 4px 0 14px; font-weight: 600; }
  label { font-size: 14px; color: #52606d; display: block; margin-bottom: 4px; }
  textarea { width: 100%; height: 150px; font: 14px/1.4 ui-monospace, Consolas, monospace; padding: 8px; border: 1px solid #b8c2cc; border-radius: 8px; background: #fff; }
</style>
</head>
<body>
<div class="wrap">
  <h1>Timing sheet</h1>
  <p class="hint">Change the start time or any length in minutes. Every clock time below updates. Then paste the list at the bottom into your AI chat.</p>

  <div class="start">
    <label for="start" style="margin:0">Starts at</label>
    <input type="time" id="start" value="14:00">
  </div>

  <table>
    <thead><tr><th>Time</th><th>Item</th><th>Min</th><th></th></tr></thead>
    <tbody id="rows"></tbody>
  </table>

  <form class="add" id="addForm">
    <input type="text" id="newName" placeholder="Add an item, e.g. Second reading" aria-label="New item name">
    <button class="go" type="submit">Add</button>
  </form>

  <p class="sum" id="sum"></p>

  <label for="out">Plain list to paste into the chat</label>
  <textarea id="out" readonly></textarea>
</div>

<script>
  const items = [
    { name: 'Gathering music', min: 10 },
    { name: 'Welcome', min: 5 },
    { name: 'A reading', min: 5 },
    { name: 'Remembering Joan', min: 10 },
    { name: 'A song she loved', min: 5 },
    { name: 'Open sharing', min: 20 },
    { name: 'Photographs', min: 5 },
    { name: 'Closing words', min: 5 }
  ];
  const rows = document.getElementById('rows');
  const startEl = document.getElementById('start');

  function clock(total) {
    const h24 = Math.floor(total / 60) % 24;
    const m = total % 60;
    const h = h24 % 12 === 0 ? 12 : h24 % 12;
    return h + ':' + String(m).padStart(2, '0') + (h24 < 12 ? ' am' : ' pm');
  }

  function render() {
    const parts = startEl.value.split(':');
    let t = (parseInt(parts[0], 10) || 0) * 60 + (parseInt(parts[1], 10) || 0);
    const first = t;
    rows.innerHTML = '';
    const lines = [];
    items.forEach((it, i) => {
      const tr = document.createElement('tr');
      tr.innerHTML = '<td class="t"></td><td class="n"></td>' +
        '<td class="m"><input type="number" min="1" max="120" aria-label="Minutes"></td>' +
        '<td class="x"><button type="button" aria-label="Remove">&times;</button></td>';
      tr.children[0].textContent = clock(t);
      tr.children[1].textContent = it.name;
      const num = tr.querySelector('input');
      num.value = it.min;
      num.addEventListener('change', () => { it.min = Math.max(1, parseInt(num.value, 10) || 1); render(); });
      tr.querySelector('button').addEventListener('click', () => { items.splice(i, 1); render(); });
      rows.appendChild(tr);
      lines.push(clock(t) + ' ' + it.name);
      t += it.min;
    });
    lines.push(clock(t) + ' Tea, cake and conversation');
    document.getElementById('sum').textContent =
      'The service runs ' + (t - first) + ' minutes, ending at ' + clock(t) + '.';
    document.getElementById('out').value = lines.join('\n');
  }

  startEl.addEventListener('change', render);
  document.getElementById('addForm').addEventListener('submit', (e) => {
    e.preventDefault();
    const box = document.getElementById('newName');
    const name = box.value.trim();
    if (!name) return;
    items.push({ name: name, min: 5 });
    box.value = '';
    render();
  });
  render();
</script>
</body>
</html>
Change the start time or any length in minutes and every clock time updates. Copy the plain list into your chat.

Paste the new list into the chat and say what changed, for example that open sharing now starts at 2:35. Copy the new HTML, replace the old code in NOS, and the same link shows it. Add a line at the top saying what changed.

A visitor can open a reading or press a button, but nothing they do is saved. In View mode, the owner's own changes, such as ticks and added rows, are saved. Treat the page as something you publish, not a form guests fill in.

A program can travel three ways. They differ most on the day you find a mistake.

A corrected time reaches everyone through a link, but not through copies already sent or printed.
A corrected time reaches everyone through a link, but not through copies already sent or printed.
Printed sheet Attachment Link
Needs an account to open No No, but opening depends on the phone and the mail app No
Fix a time after sending Reprint. Copies already handed out stay as they were Send the file again. The old one stays in inboxes Edit the page. The same link shows the new version
Everyone sees the same version Only if you collect the old ones Only if everyone opens the newest Yes

A link and a printed sheet work well together. Print the sheet for the day and say on it that the page has the latest order. Share a file without login compares more ways to send.

When it does not work

What you see Cause Fix
A time or a name is wrong The AI guessed a detail, or a line was mistyped Correct it in the chat, copy the new version, paste it again
A picture is an empty box The page asks another website for the image Ask the AI to draw it as inline SVG, and check on a phone
The text is tiny on a phone The page has no phone sizing Ask the chat to make it work on a phone
Someone cannot open an attached file An attachment depends on the phone and the app Send the link, see open HTML on a phone
People ask for a password NOS has no password feature Send the link only to the people you choose
A guest's tick or added line vanishes A visitor's changes are not saved Make the change yourself in the page
Printed sheets show the old time They were printed before the change Say on the sheet that the page is the current order

Questions people ask

Is a celebration of life program different from a funeral program?

Both are an order of service: what happens, in what order, and who takes part. The name follows the kind of gathering your family has chosen. The page works the same either way, so use the words your family uses.

Can I put a photograph on the page?

Pictures loaded from other websites are blocked on shared pages, so a photo that lives on another site will show as an empty box. The example draws a simple emblem instead. If you want a photograph, test the page on a phone before you send it, and check that it shows.

Can guests reply or add a memory on the page?

Not directly. A form inside the page cannot send its answers to a server. Ask people to reply to your message, and add what they send to the page yourself. The same link then shows it.

Is the link private?

It is unlisted, not locked. Anyone who has the link can open the page without an account, and there is no password feature. Send it in messages to the people you choose, and keep a home address or phone number off the page.

Can I change the program after I have sent the link?

Yes. Edit the page and the same link shows the new version. Visitors cannot edit it. It is worth adding a short note at the top saying what changed, so people who saw the first version notice.

Keep reading