Skip to content

Guest blog post submissions (footer link, signed-in form, staff email) - #52

Merged
mykolamelnykml merged 1 commit into
mainfrom
post-submissions
Oct 8, 2026
Merged

mykolamelnykml merged 1 commit into
mainfrom
post-submissions

Conversation

@mykolamelnykml

Copy link
Copy Markdown
Contributor

Summary

Readers can now pitch a guest post. A footer link, Submit a post, opens /submit-post. The page is public, but the form needs a signed-in account; the first Google sign-in creates one.

Posts are MDX built into the frontend, so a submission is a review queue row and never a page. Accepting one publishes nothing by itself.

  • Form:
    • The post: title, summary, tags, and a markdown body in @uiw/react-md-editor. The editor loads client-only and previews through our own <Markdown>, so raw HTML stays as text.
    • The byline: name, role, bio and up to three links.
  • Backend: a new apps/blog/ app.
    • POST /blog/submissions stores a PostSubmission as pending.
    • GET /blog/submissions lists the caller's own submissions.
    • Writes go through services.py, and refusals reach the form as a 422 detail.
  • Staff email: post_submission_staff_notice goes to every active staff account after commit. It carries an excerpt and an admin link.
  • Limits:
    • Body: 300 to 60,000 characters.
    • Per account: 3 pending posts and 5 submissions a day.
    • Tags and links: at most 8 tags, and author links go through validate_external_url.
    • All of these are settings, documented in .env.example.
  • Admin:
    • The post is shown read-only.
    • Accept and reject actions record who decided and when.
    • Only the note to the writer is editable.
    • A Download .mdx link gives the post with front matter filled in and draft: true.
  • Activity page: /activity gains a "Posts you submitted" section with the status and the editor's note.
  • Also: /submit-post is added to the sitemap. DEVELOPMENT.md and CLAUDE.md describe the flow.

Publishing an accepted post (manual)

  1. Download the .mdx file from the admin.
  2. Register the author in src/lib/blog/authors.ts and add their id to authors.
  3. Drop the file into frontend/content/blog/ and commit it.

Test plan

  • make backend-test, without the full benchmark suite (as CI runs it), passes: 612 passed. This includes new API, services, email and admin tests.
  • make frontend-test passes: 934 passed.
  • make lint passes.
  • next build compiles /submit-post.
  • make schema leaves the generated files unchanged.
  • Signed out, /submit-post shows the sign-in prompt, and the API returns 401.
  • Signed in, submit a post. Check the editor in light and dark mode, the staff email in Mailpit, and accept/reject plus the .mdx download in the admin.

A footer link, "Submit a post", leads to `/submit-post`. The page is public;
the form needs a signed-in account (the first Google sign-in creates one).
Submissions live in a new `apps/blog/` app as a review queue: posts are MDX
in the frontend, so accepting one publishes nothing by itself.

- The form takes a title, summary, tags, a markdown body in
  `@uiw/react-md-editor` (client-only, previewing through our own
  `<Markdown>`), and a byline: name, role, bio and up to three links.
- `POST /blog/submissions` stores the post as `pending` and queues
  `post_submission_staff_notice` to every active staff account after commit,
  with an excerpt and a link to the admin.
- Limits: a 300-60,000 character body, 3 pending posts and 5 submissions a
  day per account, 8 tags, author links through `validate_external_url`.
- The admin shows the post read-only, accepts or rejects it through
  `services.review`, and offers it as a `.mdx` file with the frontmatter
  filled in and `draft: true`.
- `/activity` gains "Posts you submitted", with the status and the editor's
  note. `/submit-post` joins the sitemap.
- DEVELOPMENT.md and CLAUDE.md describe the flow.
@mykolamelnykml
mykolamelnykml merged commit d5279f9 into main Oct 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant