The forum

A worked example: the Stardot BBC Micro forum, served as Viewdata. It is the service the framework was extracted from, so its numbering, its archive, its polite crawl and its reading of phpBB’s HTML are its own; the framework holds only the connection, the session and the wire.

The numbering

Every identifier in it is the board’s own — a post, forum, topic or contributor id — so a page number means the same thing on the web forum as on a BBC Micro:

<root>          the namespace's index
<root>1         search within it        (reserved, not yet built)
<root>2<id>     one member of it

0     title frame         (unkeyable: see below)
1     service root        11  search everything
3     days index          32<YYYYMMDD>   3220260802
4     forums index    41 search   42<forum>  4253
5     contributors    51 search   52<user>   5210058
7     topics index    71 search   72<topic>  7233387
8     latest posts    81 search   82<post>   82489493
9     system          90 logoff   91 how to get about
2, 6                reserved

Running it

uv run stardot-viewdata ingest --seed    # fill the archive first (about an hour)
uv run stardot-viewdata serve            # then answer calls on port 16650
uv run stardot-viewdata render --page 8  # or just draw a page

The latest posts

The service takes an open archive, so a handful of posts held in memory draws a real page offline:

from datetime import datetime, timedelta, timezone

from stardot_viewdata import build_application
from stardot_viewdata.model import Post
from stardot_viewdata.store.repository import Repository

BST = timezone(timedelta(hours=1))
archive = Repository.in_memory()
for offset in range(6):
    archive.add_post(
        Post(
            post_id=489000 + offset,
            forum_id=53,
            forum_name="new projects in development: games",
            topic_id=33387,
            author_id=10058,
            author_name="Iapetus",
            subject=f"Re: Head over Heels, part {offset + 1}",
            published=datetime(2026, 8, 2, 9, 0, tzinfo=BST) + timedelta(minutes=offset),
            updated=datetime(2026, 8, 2, 9, 0, tzinfo=BST) + timedelta(minutes=offset),
            url=f"https://stardot.org.uk/forums/viewtopic.php?p={489000 + offset}",
            content_html="<p>What a great project!</p>",
        )
    )

app = build_application(repository=archive)
 LATEST POSTS                         8a
  
 1  Re: Head over Heels, part 6         
   Iapetus  09:05                       
 2  Re: Head over Heels, part 5         
   Iapetus  09:04                       
 3  Re: Head over Heels, part 4         
   Iapetus  09:03                       
 4  Re: Head over Heels, part 3         
   Iapetus  09:02                       
 5  Re: Head over Heels, part 2         
   Iapetus  09:01                       
 6  Re: Head over Heels, part 1         
   Iapetus  09:00                       
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
  
 1-6 select, 0 index                    

Everything above the session deals in Post and Feed and has never heard of phpBB or HTTP: the Atom adapter is the first PostSource, and the board administrator’s phpBB extension is the intended second, arriving without disturbing the numbering, the renderer or the session. The full design is in the package’s own docs/design.md.