Author: Naveen Jejji
Published: July 31, 2026
The project
Collaborative Notes is a small web app where signed-in users share a single live notebook: anyone can create a note, anyone signed in can edit anyone else's note, and edits appear for every other open tab or user instantly no refresh button, no polling. Notes can carry an image or PDF attachment with an inline preview. Only the original creator of a note can delete it.
It's a deliberately "boring" app on the surface notes, not rocket science chosen specifically because real-time multi-user collaboration, file uploads and ownership-based permissions together are a genuine stress test for a backend, not a toy demo.
The Oracle technology behind it
The backend is Oracle Backend with Firebase APIs a free feature of Oracle REST Data Services (ORDS) that lets you write against Oracle AI Database using the same open-source Firebase client SDKs developers already know: authentication, a Firestore-shaped document API, object storage, and declarative security rules.
There's no separate backend service to stand up and no additional license — if you're already running ORDS, this rides on top of it.
That matters for this specific app in three concrete ways.
1. Real-time sync via onSnapshot
The entire "collaborative" feel of the app comes from a single live query listener instead of a fetch-on-demand call:
function startNotesListener() {
const notesQuery = query(collection(db, "notes"), orderBy("updatedAt", "desc"), limit(100));
onSnapshot(
notesQuery,
(snapshot) => {
state.notes = snapshot.docs.map((d) => ({ id: d.id, ...d.data() }));
renderNotes();
},
(error) => {
renderStatus(error.message, "error");
}
);
}
Every create, edit, and delete from any user, any tab refires this callback automatically.
The UI just re-renders from whatever the current snapshot is. There's no manual "refresh" logic anywhere in the app for the notes list.
2. File uploads with inline preview
Attaching an image or PDF to a note uses the same Storage API shape as Firebase Storage upload, then resolve a download URL:
async function uploadAttachment(noteId, file) {
const fileRef = ref(storage, `notes/${noteId}/${file.name}`);
await uploadBytes(fileRef, file, { contentType: file.type || "application/octet-stream" });
const url = await getDownloadURL(fileRef);
return { attachmentURL: url, attachmentType: file.type, attachmentName: file.name };
}
The app then renders an <img> thumbnail for images or an inline <embed> preview for PDFs, so attachments are visible in the shared list without leaving the page.
3. A collaborative permission model, enforced server-side
This is the detail I think is most worth highlighting. "Collaborative" here specifically means: any signed-in user can edit any note, but only the creator can delete it. That's not a client-side convention I'm trusting the UI to respect — it's a security rule evaluated on the backend, independent of the JavaScript running in someone's browser:
- Create: allowed if the signed-in user is the one being set as the note's owner
- Update: allowed for any signed-in user (this is what makes it collaborative rather than single-owner)
- Delete: allowed only if the requesting user's ID matches the note's owner field
A user can't just edit the DOM or replay a request to bypass this the rule lives next to the data, not in the page.
What users actually get out of this
- No merge conflicts to think about. Because everyone sees the current state live, the odds of two people editing stale versions of the same note drop sharply compared to a "refresh to see changes" model.
- Real collaboration, not just shared storage. Anyone can pick up and extend anyone else's note closer to a shared whiteboard than a personal to-do list.
- Attachments that are actually usable, not just links you have to download and open separately.
- A permission model that's actually enforced, not just implied by what buttons happen to be visible in the UI.
- Zero additional backend cost or infrastructure for teams already running Oracle Database + ORDS this is additive, not a new system to operate.
How it's deployed
The backend runs as two containers (Oracle Database Free 26ai + ORDS) via Podman, with the frontend as a plain static site (HTML/CSS/vanilla JS with ES module import maps no build step, no framework).
The static UI is also published via GitHub Pages for browsing the interface live data operations require the Oracle Backend with Firebase APIs instance to be reachable, same as any app that talks to its own backend.
Try it / read the code
- Source: https://github.com/naveen-6735/collaborative-notes-web
- The workshop this environment is built on: RecipeShare — Oracle LiveLabs (Web)
- Oracle Backend with Firebase APIs — landing page
- Announcement post
- Developer docs
If you build something with this toolkit, I'd genuinely like to hear about it.


Top comments (0)