Skip to content

[#206] Create Storyline with 5-state publishing flow#65

Merged
realproject7 merged 2 commits intomainfrom
task/206-create-storyline
Mar 14, 2026
Merged

[#206] Create Storyline with 5-state publishing flow#65
realproject7 merged 2 commits intomainfrom
task/206-create-storyline

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Create /create route with storyline form (title, content, deadline toggle)
  • Implement usePublishStoryline hook with 5-state machine:
    uploading -> confirming -> pending -> indexing -> published
  • Server-side IPFS upload via /api/upload route (S3 keys stay server-side)
  • Wire createStoryline() on StoryFactory via wagmi
  • Trigger storyline indexer after tx confirmation
  • CID cached in ref for retry (skip re-upload on wallet rejection)
  • Update STORY_FACTORY constant to read from NEXT_PUBLIC_CONTRACT_ADDRESS

Files Changed

  • src/app/create/page.tsx — Create storyline form with publishing states
  • src/hooks/usePublish.ts — Publishing state machine hook
  • src/app/api/upload/route.ts — Server-side Filebase upload endpoint
  • lib/contracts/constants.ts — STORY_FACTORY reads from env var

Test plan

  • tsc --noEmit passes
  • eslint passes
  • Unicode char counter validates 500-10k range
  • CID reuse on retry skips IPFS re-upload
  • Wallet-gated with connect prompt
  • Error state allows retry

Fixes #206

🤖 Generated with Claude Code

- Create /create route with title, content textarea (Unicode char counter),
  and 72h deadline toggle
- Implement usePublishStoryline hook with 5 states:
  uploading -> confirming -> pending -> indexing -> published
- Wire Filebase upload via /api/upload server route (keeps S3 keys server-side)
- Call createStoryline() on StoryFactory via wagmi writeContractAsync
- Trigger storyline indexer after tx confirmation
- Cache CID in ref for retry (skip re-upload on wallet rejection)
- Update STORY_FACTORY constant to read from NEXT_PUBLIC_CONTRACT_ADDRESS env
- Wallet-gated with ConnectWallet prompt
- Terminal aesthetic form styling

Fixes #206

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The overall flow is in place, but there are two correctness issues in the publish hook that can break publishing or index the wrong content after a retry.

Findings

  • [high] Cached CID reuse can publish mismatched content after an error.
    • File: src/hooks/usePublish.ts:35
    • Suggestion: Invalidate the cached CID when the form content changes, or cache both CID and the exact content/hash it was derived from and only reuse it when they still match.
  • [high] The tx confirmation fallback calls /api/tx-status, but that route is not added in this PR or present on main, so the imperative confirmation path can time out even after a successful transaction.
    • File: src/hooks/usePublish.ts:74
    • Suggestion: Either add the missing route, or wait for the transaction directly via the shared viem public client / wagmi action instead of polling a nonexistent endpoint.

Decision

Requesting changes because these issues can cause failed publishing flows or mismatched indexed content in a core user path.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b Review: APPROVED

Solid publishing flow. Findings:

  1. 5-state machine — idle/uploading/confirming/pending/indexing/published/error. Clean separation, UI reflects each state accurately. Error state allows retry.
  2. CID cachinguseRef preserves CID across retries so wallet rejection doesn't re-upload. Cleared on success or reset. Correct pattern.
  3. Upload route — server-side, keeps S3 keys out of the client. Validates input, wraps uploadWithRetry.
  4. STORY_FACTORY from env — reads NEXT_PUBLIC_CONTRACT_ADDRESS with zero-address fallback, typed as 0x${string}. Unblocks the operator gate.
  5. Form UX — Unicode-aware char counter, disabled inputs during publishing, deadline toggle with explanation text. All correct per §4.1 spec.

Minor note (non-blocking): In usePublish.ts:80, txConfirmed in the polling loop captures a stale closure value from the render. The /api/tx-status backup fetch mitigates this, so it works in practice. A future refactor could use a ref for txConfirmed or rely solely on the fetch-based polling.

  1. CI green.

Approving — the stale closure is a minor edge that doesn't affect correctness given the backup check.

…aitForTransactionReceipt

- Cache CID with content hash; invalidate when content changes (fixes
  mismatched content on retry after edit)
- Replace /api/tx-status polling with publicClient.waitForTransactionReceipt()
  (removes dependency on non-existent route)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b Re-review: APPROVED

Both fixes verified:

  1. CID cache with content hash — cache now stores { cid, contentHash } and invalidates when content changes. Prevents stale CID reuse if the user edits content between retries.
  2. publicClient.waitForTransactionReceipt() — replaced the polling loop + stale txConfirmed closure with a single viem call. Much cleaner, no closure issues, no dependency on /api/tx-status. txConfirmed removed from useCallback deps accordingly.

CI green.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The follow-up fixes the two blocking correctness issues in the publishing flow: CID reuse is now tied to the content hash, and transaction confirmation waits on the shared viem public client instead of a nonexistent API route. The repository check is passing.

Findings

  • None.

Decision

Approving because the 5-state create-storyline flow is now consistent end-to-end with the current RPC, contract, and indexer setup, and the previously identified correctness risks are addressed.

@realproject7 realproject7 merged commit 94fd1f4 into main Mar 14, 2026
1 check passed
realproject7 added a commit that referenced this pull request Mar 23, 2026
New address: 0xAe50C9444DA2Ac80B209dC8B416d1B4A7D3939B0
Fixes USDC zap mint that was reverting due to V4 Router encoding mismatch.
See plotlink-contracts PR #65 for root cause analysis.

Fixes #470

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants