Nobody has started this yet — be first.
Business impact
prisma/schema.prisma's Comment model is explicit about the intended design: "Stretch goal: optional self-relation for one level of threaded replies. A reply's parentCommentId must point at a comment on the SAME post; that cross-check is enforced in application code." The same-post cross-check is indeed enforced (POST /:id/comments rejects a parentCommentId from a different post). But nothing enforces the one level part: the handler only checks that the target parentCommentId exists and belongs to the same post -- it never checks whether that target is itself already a reply. Right now you can reply to a reply, then reply to that reply, indefinitely.
Problem
POST /posts/:id/comments with a parentCommentId that points at a comment which is itself a reply (i.e. that comment's own parentCommentId is not null) is currently accepted (201), when it should be rejected -- nothing in the handler checks the parent's own parentCommentId.
Current behavior
Replying to a reply -- and replying to that reply, and so on -- succeeds indefinitely, producing threads nested arbitrarily deep even though the schema and serializer were only ever designed for one level.
Expected behavior
POST /posts/:id/comments with a parentCommentId that points at a comment which is itself a reply (i.e. that comment's own parentCommentId is not null) is rejected with 400 BAD_REQUEST, same status/shape as the existing "different post" rejection. Replying to an actual top-level comment (parentCommentId === null) continues to work exactly as it does today.
Steps to reproduce
cd nodejs/blog_api
node_modules/.bin/jest --config practice-tickets/jest.config.js
practice-tickets/tests/ticket05_reply_to_reply_allowed.test.js --verbose
Why this matters
The nested-replies feature was deliberately scoped to one level -- the replies relation in the schema and the serializer (serializeComment in src/lib/serialize.js) only render one level of nesting under each top-level comment, with no recursive UI concept for deeper threads. Allowing deeper nesting today doesn't crash anything, but it silently produces data the rest of the system was never designed to display (a reply-to-a-reply exists in the database but has no home in any listing response, since GET /posts/:id/comments only nests replies one level under each top-level comment).
Suggested approach
In the if (parentCommentId !== undefined) block of POST /:id/comments in src/routes/posts.js, the code already fetches parent and checks parent.postId !== postId. Extend that same check using a field already present on parent -- the point of the "one level" rule is that a valid reply target must itself be a top-level comment.
Acceptance criteria
Verification
node_modules/.bin/jest --config practice-tickets/jest.config.js practice-tickets/tests/ticket05_reply_to_reply_allowed.test.js --verbose
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b feat/reply-to-reply-allowedFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/reply-to-reply-allowedSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign indocker compose down -vTo run locally without Docker, you need a local PostgreSQL instance:
npm install
cp .env.example .env # edit DATABASE_URL, JWT_SECRET, etc.
npm run prisma:migrate:dev # applies migrations to your local Postgres
npm run dev # starts with --watch on http://localhost:3000
Run the project's own test suite (real Postgres, not mocks -- point DATABASE_URL at a disposable database first):
npm test
Work the tickets in practice-tickets/ (ticket01 through ticket07); each has its own dedicated Jest test under practice-tickets/tests/, run via a separate Jest config (practice-tickets/jest.config.js) so plain npm test never picks them up:
docker compose up -d postgres # if it isn't already running
npm run prisma:migrate
./practice-tickets/run_tickets.sh # all 7, clean pass/fail summary
node_modules/.bin/jest --config practice-tickets/jest.config.js \
practice-tickets/tests/ticket01_pagination_skip_off_by_one.test.js --verbose # a single ticket
Level 2
Implement a feature
Extend the system within its own patterns.