Repository source: docs/plans/archive/forte_compose_thread_step2_feature_description.md
Forte Compose Thread — Step 2: Feature Description
Problem
Forte's board toolbar has a "New" button that's permanently disabled — there's no way to start a new thread from within Forte at all, only to reply to existing ones.
User Stories
As a Forte board-view reader, I want to click "New" and get a dialog to write a new thread, so I don't have to leave Forte to start one.
As a Forte board-view reader who successfully creates a thread, I want to land back on the board with my new thread already selected, so I can see it in context the same way a fresh reply gets restored today.
As a Forte board-view reader, I want to dismiss the New dialog (Cancel or Esc) without side effects if I change my mind.
Core Requirements
The "New" toolbar button (
forte_board.php) becomes enabled and opens a native<dialog>element via.showModal()— a genuinely new UI pattern for this project (no<dialog>is used anywhere else in the codebase today), per the approved Step 1 decision (Option C).The dialog wraps
thread_compose_form.phpin its full (non-compact) mode — Subject, Board tags, and Body all visible — matching classic's own dedicated/compose/threadpage, not the abbreviated inline modeboard.php's compact composer uses. A standalone dialog has room for the full form, and Subject shouldn't be silently dropped the way the compact mode drops it.POST /compose/thread(handleComposeThreadSubmit()) gainsreturn_tosupport, the same shape asresolveComposeReplyReturnTo()already provides for replies: on success, the reader is redirected back to/forte(preserving the active tag filter) with the newly created thread selected (selected={new_thread_id}) — instead of today's unconditional redirect to classic's/threads/{new_thread_id}. This is simpler than the reply case: the server always knows the new thread's ID at redirect time, so the client only needs to supply which tag was active, not which thread to select.No signed-identity support for thread creation in this cycle — new threads created via the dialog always post anonymously (
author_identity_idstays empty,thread_compose_form.php's existing default). Reason:lazy_compose_signing.jsbinds to exactly one[data-compose-root]per page (document.querySelector, notquerySelectorAll) — Forte's board page already spends that one slot on the Reply panel. Making the New dialog signed too would need a real fix to that shared script's single-root assumption, which is out of scope here; the original flagged authorship gap (forte_identity_signing) was specifically about replies, not thread creation, so this isn't a regression, just an explicit, recorded exclusion.Validation-error handling matches the same known, accepted limitation
forte_replyStage 5 already established for replies: a failed submission redirects to classic's compose-error rendering (renderComposeThreadPage()), not a Forte-styled inline error. Not fixed here.No changes to classic's own
/compose/threadpage orboard.php's inline compact composer — both keep usingthread_compose_form.phpexactly as they do today.
Shared Component Inventory
thread_compose_form.php— reused unchanged, rendered withcompact => falseinside the new dialog (the same modecompose_thread.phpalready uses).handleComposeThreadSubmit()/POST /compose/thread— extended withreturn_tohandling, mirroring the existingresolveComposeReplyReturnTo()pattern for replies (a new sibling helper, not a modification of the reply one).paned_board_reader.js— extended to open/close the new dialog from the "New" toolbar button and to keep the existingselected=/board-restore logic working for a freshly created thread the same way it already does for an existing one.forte.css— extended with<dialog>-specific styling consistent with the paned window's existing look (matching the congruence approach already used for.paned-compose-form/.paned-compose-status).lazy_compose_signing.js/browser_signing.js— not touched; deliberately not wired to the New dialog (see Core Requirements).
Simple User Flow
Reader clicks "New" on the board toolbar.
A dialog opens with Subject, Board tags, and Body fields (same shape as classic's
/compose/thread).Reader submits; on success, they land back on
/fortewith their tag filter preserved and the new thread selected in the list.Reader can instead Cancel or press Esc to close the dialog with no thread created.
Success Criteria
The "New" button is no longer
disabledand opens a working dialog.Submitting the dialog's form creates a thread identical in every way to one created via classic's
/compose/thread(same write path, same validation).A successful submission returns the reader to
/forte— never to classic — with the tag filter preserved and the new thread selected.Canceling the dialog (Cancel control or Esc) closes it with no thread created and no other side effects.
Classic's
/compose/threadpage andboard.php's inline compose-thread flow are both completely unaffected.