This morning, I moved the Dreamcoded community from a working forum towards something that feels like a real part of the site.

The underlying account, discussion and moderation systems already existed. The work today was about what happens around them: knowing when somebody joins, helping members catch up, making the interface work as an app on large and small screens, and giving posts a better writing experience.

By the end of the morning, registration was open, the community had its own responsive layout and members had a clear way to see what had happened since their last visit.

Opening registration without losing visibility

The first change was small from a member's point of view but important for running the community. I added an optional email notification for new registrations.

When the setting is enabled, every active administrator with a verified email address receives a branded message containing the new member's username, email address, join time and account ID. The message also links directly to the member-management screen.

I kept the notification separate from the registration itself. A delivery failure is logged, but it does not stop the new member receiving their sign-in link or creating an account. That distinction matters: an administrative convenience should not become another way for registration to fail.

I also extracted the shared email design so sign-in, verification and new-member messages use the same structure without duplicating the whole template. With that in place, I enabled production registration and added tests for both sides of the switch: no notification when it is disabled, and notifications only to verified active administrators when it is enabled.

Remembering what each member has seen

Opening the doors created the next problem. A list of discussions is useful on a first visit, but returning members also need to know what changed while they were away.

I built a new Activity page for logged-in members. It shows visible topics and replies posted since that member last checked the feed, with an unread count in the navigation. Each entry includes the discussion, category, author, date and a short plain-text excerpt, and links to the exact post even when it sits on a later page of replies.

The obvious implementation would have been to compare posts with the last login time. I did not use that because signing in is not the same as reading the activity feed, and it would behave differently across browsers and devices.

Instead, each account now stores the ID of the last visible post it has seen. When the member opens Activity, the page takes a fixed lower and upper post ID for that reading session. Those boundaries stay in the pagination links, so a new reply cannot arrive halfway through and push an older entry onto a different page.

Existing accounts start at the migration point rather than receiving the entire archive as unread. New accounts start at the newest visible post when they are created. The result is a small amount of stored state that works consistently wherever the member signs in.

Turning forum pages into an app shell

The community still looked too much like ordinary site pages with forum controls added to them. I rebuilt the layout around the way people actually move through discussions.

On a wide screen, the community now has a dedicated header and a three-part layout: persistent navigation and categories on the left, the current feed or page in the centre, and contextual guidance on the right. Discussion cards became denser and easier to scan, with their category, activity date, author and reply count arranged around the title and excerpt.

On smaller screens, the left rail becomes an off-canvas drawer and the most useful destinations move into a fixed five-item tab bar. The middle action changes according to the member's state: joining for a visitor and starting a topic for somebody who is signed in. The category control opens the drawer without taking an anonymous visitor away from the page they are reading.

The JavaScript is an enhancement rather than a requirement. Without it, the navigation remains in normal document flow and every destination is still available. I also added Escape-key handling, focus restoration and a scrim for the open drawer.

The first redesign pass still left several controls competing for attention. I removed repeated “Start a topic” actions from the desktop navigation and feed header, moved the mobile menu to the right side, and replaced separate menu icons with one animated control shared by the main website and the community. I also made the Turnstile challenge flexible-width and added a narrow-screen fallback for devices around 340 pixels wide.

One useful structural change came out of that work: categories are now loaded into the app shell for every community page. They are available from rules, login and registration screens rather than only from the discussion index.

Giving administrators a trusted publishing path

The ordinary posting rules are deliberately restrictive. New and regular members have cooldowns and daily limits, duplicate detection, link restrictions and a hidden-field spam trap. Those are useful protections for public submissions, but they also stopped me using the community for official posts containing links.

I added a separate publishing path for administrators. Admin topics, replies and edits can contain normal Markdown links and are not blocked by the member spam checks, duplicate detection, cooldowns or posting quotas.

That bypass is narrower than it sounds. The administrator still needs an active account, a valid session and a verified email address. Locked categories and discussions remain locked. Raw HTML is still escaped rather than executed, and external links open with the appropriate isolation attributes. Moderators do not receive the same exemption.

Keeping those boundaries explicit was more important than simply removing validation. The aim was to let a trusted account publish useful resources, not to create an unrestricted route around the community's security model.

Making Markdown easier to use

The last change of the morning was the most visible while writing a post: a formatting toolbar above the Markdown editor.

Members can add a second-level heading, bold or italic text, bulleted and numbered lists, quotes, inline code and code blocks without remembering the syntax. Administrators also receive a link control. The buttons work with the current selection, and the bold and italic actions have the familiar keyboard shortcuts.

I kept the textarea as the source of truth. The toolbar only inserts Markdown, so posting and editing still work without JavaScript. Screen-reader announcements report each formatting action, and the controls are hidden until the enhancement is ready.

Browser coverage now checks the selection-aware formatting directly, while the integration tests confirm that the link button only appears for administrators. The security tests also verify the more important boundary: administrator links render, but an attempted script remains harmless text.

Where the community stands now

This morning's work did not add one enormous feature. It connected several smaller pieces that make the community easier to operate and easier to return to.

New members can register, I can see when they arrive, and returning members can catch up without rereading every discussion. The interface now has a distinct desktop and mobile structure, categories remain within reach across the app, and the editor gives people useful formatting without hiding the Markdown underneath.

There are still deliberate limits. Ordinary members cannot post links or uploads, and the community remains a young system that needs real use before its navigation and moderation assumptions can be considered settled. For now, though, it feels much less like a set of forum routes and much more like a place where conversations can begin.