Uploading "Memory Road interior 12-28.pdf" produced a book, a run and a
storyboard all headed "Memory Road interior 12-28". The title is derived from
the filename because that is the only thing an upload carries, and publishers
name files after print runs.
Guessing harder is the wrong fix - stripping "interior 12-28" would be a rule
that works on one file. Letting the author type the title takes eight lines and
is right for every file. The author field goes in at the same time; it costs
nothing and a trailer should know whose book it is.
"Drop the manuscript here or click to choose a file" is a drop zone pretending
to be a button - it reads as an instruction rather than a control, and on a
laptop nobody drags a file from anywhere. There is now an actual button. The
zone still accepts a drop, because that costs nothing once the button exists.
The paste box is gone. It was there for a manuscript that would not upload
cleanly, but a book is 100,000 words and nobody pastes that; keeping it meant
offering a route that only works for the case it was not for. Word and PDF
cover it, and a PDF that turns out to be a scan is refused with the reason.
Takes a .docx, a text .pdf or a .txt up to 6MB, or pasted text for anything
that will not upload cleanly. The upload itself only stores the file and writes
a row - extraction runs afterwards on the server, because ptl_api is
synchronous with a five second budget and parsing a novel is not a five second
job. The page polls until the book says ready, or says why it could not be
read.
readFileB64 lives here rather than in app.js: app.js's resizeImage goes through
an <img> and a canvas, which is right for a phone photo and fatal for a .docx,
and this is the only page that uploads a document.