r/webdev • u/raiyan_0001 • 1d ago
Discussion Need Help Implementing a Medium-Style Block-Based Article Editor with Cloudinary and MongoDB
Hey, I need some help understanding my development workflow. This might be a bit long, but I want to explain my problem clearly.
I’m a beginner building a small article web app where users can register, log in, and create articles containing both text and images.
I want to implement a block-based architecture, similar to Medium, where users can add text and images in any order. For example, they might write a paragraph, insert an image, write another paragraph, and then insert another image. I’m storing these blocks in an array in my article schema so that their order is preserved.
My main confusion is about image uploads. When a user selects an image, I want to upload it to Cloudinary, receive the image URL, and store that URL inside the corresponding image block in the article.
However, I’m struggling to understand how to connect all these steps. I’ve tried implementing it and asking ChatGPT for help, but I still haven’t understood the workflow properly.
I’d like a beginner-friendly, step-by-step explanation of how to implement this, including how the frontend editor manages the blocks, how the image is uploaded to Cloudinary through the backend, how the returned URL is added to the correct block, and how the complete article is eventually saved to MongoDB.
Please explain the logic behind each step rather than just giving me code, so I can understand the implementation and build it myself.
1
u/Over_Problem_3600 1d ago
give every block an id the moment it's created. that's what made it clock for me, the upload finishes, you find the block by id and set the url
1
u/PrimaryFamous6139 full-stack 1d ago
Give each block a unique ID and type (text or image). When a user selects an image, upload it through your backend to Cloudinary, then update the matching image block with the returned URL using its ID, not its array index. When they click Publish, send the entire blocks array to your backend and save it in MongoDB. Cloudinary stores images, MongoDB stores URLs and block order, and the frontend manages the editor state
1
u/c1rno123 1d ago
I'd start with invariants:
- The client owns the state
- The backend is stateless. It validates each request and keeps the DB consistent
The backend (already?) provide atomic operations for adding/removing/shifting blocks.
For images, I'd use a separate Media/Blob entity. Give it a lifecycle such as created → ready.
- The client asks the backend to create a media record.
- The backend creates it with status: "created" and returns an upload URL.
- The client uploads the file using that URL.
- The client tells the backend the upload is complete. The backend verifies it and marks the media record ready.
- The client adds an image block containing the media ID.
When saving the article, the backend checks that each referenced media record exists and is ready.
1
u/Living-Inspection653 23h ago
A standard workflow for block-based image uploads consists of three steps: 1) Temporary/Local State: When a user inserts an image block, show a local preview or loading state in the editor block list. 2) Direct or Proxy Upload: Send the image file to your backend (or directly to Cloudinary using signed upload presets). Once Cloudinary responds with the secure URL, update the specific block's payload in your frontend state from the temporary file/preview to the Cloudinary URL. 3) Persistence: When the user clicks Save Article, send the array of block objects (including type, content, and Cloudinary URLs for image blocks) in a single POST/PUT request to MongoDB. This keeps image uploads async and unblocks article submission.
1
u/Miserable-Money642 22h ago
One edge case worth testing: start two uploads, reorder the blocks, and let them finish in reverse order. Update each block by its stable ID, never by its array index or whichever image is currently selected, or the URLs can land on the wrong blocks. Keep an uploading or failed state per image and do not publish while an upload is still pending. For Cloudinary, use a signed upload flow and validate size and allowed formats on the server. Store the public_id as well as the URL so replaced or abandoned draft images can be cleaned up later.
1
u/HedgehogCertain 22h ago
Good thread already covered the upload flow; one thing beginners skip: don't ship the raw file to Cloudinary. A phone photo is easily 5–10 MB, so resize/compress it in the browser before upload — cap width to what the article actually displays (~1600–2000px). The upload gets much faster and you don't burn Cloudinary storage on pixels nobody sees.
Use URL.createObjectURL for the local preview while it's pending, then swap it for the Cloudinary URL once the upload resolves. You don't have to crop yourself — Cloudinary can scale on delivery with f_auto/q_auto in the URL — but that only helps after the file is already up, so trimming size beforehand still matters.
On the Mongo side, store the URL plus public_id, width, height and alt in the image block, never the binary itself, so you can clean up or replace abandoned drafts later.
1
u/Impulso_b2b 20h ago
Keep the Cloudinary API secret on the backend: the frontend sends the file to your own API route, and the backend calls the SDK's upload method (uploader.upload in Node) and returns the public_id. Save that public_id on the image block and update it by the block's unique id when the upload finishes, so reordering while an upload is pending can't attach the URL to the wrong block. Mark the block as pending until then, and block publishing while any pending blocks remain.
1
u/_CuriousCoder_ 11h ago
I'd break it down into two main parts: the frontend managing the blocks and the backend handling image uploads to Cloudinary. When a user adds an image, the frontend should send a request to the backend to create a new image block, then the backend uploads the image to Cloudinary and returns the URL to the frontend, which updates the block with the URL. The backend can use a library like Multer to handle multipart/form-data requests and upload images to Cloudinary. This way, you keep the frontend and backend logic separate and manageable.
1
u/web-dev-kev 1d ago
I’m a beginner building a small article web app where users can register, log in, and create articles containing both text and images.
I'd say this is not a beginner project.
Love your enthusiasm, and you're taking the right approach, but what maters here is not how big the app is, but how complex it is.
You're basically building WordPress!
0
u/raiyan_0001 1d ago
Im confused after making login and register
Idk if i ever be able to complete this project but i wanna make it
0
u/web-dev-kev 23h ago
Then I'd stop now.
It's a wonderful goal, and I hope you get there, btu you have no idea of the complexity this involves.
2
u/ExtensionEmotion7136 1d ago
the key is treating each block as its own little unit of data before you ever think about saving the whole article. when a user drops an image in, you fire off the upload right then to your backend, get the url back, and swap the placeholder in that block with the real cloudinary link. only when they hit publish do you string all those blocks together and send the whole array to your db