ShareMyPage

Live pages

Polls, forms, checklists and reactions turn a shared page into something readers can act on. Responses are stored for you, with no backend, no API key, and no JavaScript of your own.

A shared page is usually something people read. A live block lets them act on it: vote, submit, tick, add, upvote, react. You drop one tag into your HTML and the storage is handled.

No backend. No API key. No JavaScript of your own. The block is the whole contract.

Which block do I want

The question that decides it is who writes, and who gets to see it.

I want readers toUseEveryone sees
choose between options I wrote<smp-poll>the tallies
send me something private<smp-form>nothing, only you
tick off shared work<smp-checklist>the ticks
add items others can see and back<smp-checklist allow-add allow-vote>the items and their scores
signal they saw it, without writing<smp-reactions>the counts

The split that catches people out is form versus checklist. A form's submissions are private to you and never appear on the page. A checklist is shared, and allow-add extends that to the items themselves. If a reader should add something the next reader can see, that is the checklist, not the form.

What every block shares

These rules hold for all of them, so the sections below only cover what is particular to each.

An id is required, and permanent. It is the key responses are filed under. Keep it unique on the page and do not change it later; changing it orphans everything collected so far.

Everything is anonymous. A block shows that eleven people reacted or that an item is ticked, never who. Only a form knows who wrote what, and only in your own export. For attribution, use comments instead.

Broken markup degrades, it never breaks the page. A block with no id, or with no usable children, is left exactly as the plain text you wrote. A typo costs you the feature, not the page.

Your CSS owns the look. Blocks render into your page's own HTML with no styling of their own, and expose data-smp-* hooks to style against. Each section lists its own; the convention is [data-smp-<thing>] for elements and data-smp-<thing>-count for numbers, so a progress readout or a highlight is CSS alone.

Other people's changes arrive on their own. Every block re-reads every few seconds and when you return to the tab, so two people on the same page stay in step without refreshing.

You can close or reset any of them. Open the page's settings, and under Responses: Close freezes a block read-only, Reset clears it for a fresh run. Responses only appears once a page actually has live blocks on it.

Fair-use caps apply: a per-page response cap plus per-visitor and per-IP rate limits. Sized for pages that collect responses, not for high-volume data collection. See Data and backends if you are past that, or need to read individual rows back.


Polls

<smp-poll id="lunch">
  <smp-poll-question>Where are we going?</smp-poll-question>
  <smp-poll-option value="sushi">Sushi</smp-poll-option>
  <smp-poll-option value="pizza">Pizza</smp-poll-option>
</smp-poll>

Each option becomes a button with a live count and bar. One choice per person: clicking a second option moves your vote rather than adding one.

  • <smp-poll-question> is optional; any text you already have works as the question.
  • Each <smp-poll-option value="..."> needs a stable value. The text inside the tag is the visible label.
  • Add require-name plus one <input data-smp-name> on the page to capture each voter's name into your export. The vote is blocked until it is filled, and the block gets data-smp-need-name so your CSS can prompt.

Hooks: [data-smp-poll="id"] on the container with data-smp-total; [data-smp-poll-option="value"] on each button, with [data-smp-poll-count] and [data-smp-poll-bar] inside; data-smp-poll-closed when closed.

For picking several things at once, a poll is the wrong shape: use a checklist with allow-vote, which stores a row per person per item and can show which ones are yours.

Forms

<smp-form id="signup" multiple>
  <smp-field name="name" label="Your name" required></smp-field>
  <smp-field name="size" label="T-shirt size" type="select">
    <smp-option value="m">Medium</smp-option>
    <smp-option value="l">Large</smp-option>
  </smp-field>
  <smp-field name="notes" label="Anything else" type="textarea"></smp-field>
</smp-form>

Free-text intake. Submissions are private to you and never render on the page; you read them from Export CSV in the page's settings, one column per field.

  • type is one of text (default), textarea, select, radio, checkbox, number, email. The choice types take <smp-option value="..."> children.
  • required blocks submission until the field is filled.
  • multiple on the form lets one person submit more than once. Without it, a second submission replaces their first.

Hooks: [data-smp-form="id"] on the form, [data-smp-form-field="name"] on each field, [data-smp-form-submit] on the button, [data-smp-form-status] on the confirmation line.

Checklists

<smp-checklist id="launch">
  <smp-item value="copy">Finalize homepage copy</smp-item>
  <smp-item value="deploy">Deploy to staging</smp-item>
</smp-checklist>

Shared team state. When anyone ticks "Deploy to staging" it is ticked for everyone, which is what turns a launch plan into a board where the remaining work visibly shrinks.

Each <smp-item value="..."> is one to-do; value is the stable key the tick is filed under, and the text inside is the label.

Hooks: [data-smp-checklist="id"] on the container, carrying data-smp-checked-count and data-smp-total for a progress readout; [data-smp-item="value"] on each item, gaining data-smp-checked when done; [data-smp-item-label] on the item's own text (style that rather than a bare span, so you do not also catch the vote tally); data-smp-checklist-closed when closed.

[data-smp-item][data-smp-checked] [data-smp-item-label] { text-decoration: line-through; opacity: .55; }
[data-smp-checklist]::after { content: attr(data-smp-checked-count) " / " attr(data-smp-total) " done"; }

Letting readers add and upvote

A launch plan is written up front. A todo list, a shopping list or an idea board is not: the point is that people add to it.

<smp-checklist id="ideas" allow-add allow-vote sort="votes" add-label="Add an idea">
  <smp-item value="search">Better search</smp-item>
</smp-checklist>
  • allow-add grows an input, so anyone with access can add an item everyone then sees. add-label sets its placeholder and button text.
  • allow-vote puts an upvote control on each item. One vote per person per item, click again to withdraw, and you can see which ones you backed.
  • sort="votes" orders most-backed first. Ties keep their place, so a list nobody has voted on does not shuffle.
  • A checklist with allow-add and no items at all is valid, for a list that starts empty.
  • Adding something already on the list does nothing, rather than duplicating it. Anyone with access can remove an added item, the same way anyone can untick one.
  • An item is capped at 200 characters, and one list holds up to 200 reader-added items.

Hooks: [data-smp-item-added] on a reader-added item, [data-smp-item-remove] on its remove control, [data-smp-checklist-add] on the form, [data-smp-item-vote] on the upvote control (carrying data-smp-vote-count, plus data-smp-voted when you are one of the backers, and [data-smp-vote-tally] for the number).

Anything a reader types here is public to the link

This is the opposite of a form. An item someone adds is shown to everyone who can open the page, immediately, and it is anonymous: there is no record of who added what, and no way for them to take it back except by removing it for everybody. On a private page that audience is the people you invited. Think twice before putting allow-add on a public page.

Groups: giving items a status

Declare statuses and the list renders one group per status, each item filed under its own. That is a board.

<smp-checklist id="board" statuses="todo:To do, doing:In progress, done:Done"
               allow-add allow-vote sort="votes">
  <smp-item value="brief" status="done">Write the launch brief</smp-item>
</smp-checklist>
  • A comma-separated list of id:Label pairs. The first is the default, where new items land.
  • A reader-added item gets a chip showing its status; clicking it opens a dialog to pick another. An authored <smp-item status="done"> sits in that group and stays there, because its status is markup.
  • sort="votes" sorts within each group, not across the whole list.

Status is an attribute of the item, not a place it lives. Re-filing is a single write to the row already there, so an item keeps its ticks and its votes as it moves.

Hooks: [data-smp-group="id"] per group with data-smp-group-count and a [data-smp-group-label]; data-smp-item-status on each item; [data-smp-item-status-trigger] on the chip and [data-smp-status-dialog] on the dialog, whose parts are [data-smp-status-dialog-title], [data-smp-status-choice="id"] and [data-smp-status-cancel]. It is a real <dialog>, so Escape and the backdrop work on their own.

Leave statuses off and the list renders flat. Items stored before a status existed read as the first one, so adding statuses to a list you already use is safe. Renaming an item does start its votes over, because the wording is the item's identity.

Reactions

<smp-reactions id="launch-note" emoji="👍,🤔,🎉"></smp-reactions>

The lightest thing a reader can do, which is the point: someone who would never write a comment will still tap an emoji. It answers the question you have every time you share a page, did anyone actually read it.

  • emoji is optional; leave it off for a default set. Up to 12, with duplicates and over-long entries ignored so a stray sentence cannot become a button.
  • One row per person per emoji, so a reader can pick several, clicking again takes one back, and the count is a headcount, not a click count. You can see which ones you picked.

Hooks: [data-smp-reactions="id"] on the row with data-smp-reactions-total and data-smp-reactions-closed; [data-smp-reaction="👍"] on each button with data-smp-reaction-count and data-smp-reacted; [data-smp-reaction-emoji] and [data-smp-reaction-tally] inside.

See also

  • Data and backends for window.smp, the raw append-and-read stream behind these blocks, and for when you genuinely need your own API or database.
  • Comments when feedback should be attributed to a person.
  • Access for who can open a page, which is also who can act on its blocks.

On this page