@handle, separate from any project or template.
Reading and editing are different surfaces
A published post reads at/post/:slug. Editing it happens at a different URL, /post/:slug/edit, signed in and only if you’re the owner. The backend answers a plain 404 (never 403) for a post that isn’t yours, so this URL can’t be used to discover that someone else has a draft.
The editor is never indexed, and a signed-out visitor is redirected to sign in before it ever loads. Its Preview is how you see an unpublished draft rendered: the public reader at /post/:slug never serves a draft, even to its own owner.
The slug is minted once
A post’s slug, the part of the URL after/post/, is assigned the first time you publish, and frozen from then on. A draft that’s never been published has no slug yet, so its edit link addresses it by id instead; publishing is what gives it the permanent URL. This is also why you can’t change a post’s URL after the fact by renaming it later.
Posts vs. the Flowy journal
/post/:slug is for creator posts: yours. It’s a different surface from the Flowy journal at /blog/:slug, which is Flowy’s own editorial content. The two are kept apart deliberately: the journal’s URLs were already indexed before creator posts existed, so they stay at /blog/:slug rather than moving. Each surface redirects to the other if you reach it through the wrong door, so any given post resolves to exactly one canonical URL.