Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Create a Secure Document Management System in FlutterFlow

Build a document management system with Firestore collections for documents and folders supporting nested hierarchy. Each document tracks versions so every edit creates a new entry while keeping all previous versions accessible. Implement access control with per-document viewer and editor lists. Add PDF preview via a Custom Widget, tag-based search, and breadcrumb navigation for deep folder structures. Upload files through FlutterFlowUploadButton to Firebase Storage.

What you'll learn

  • How to build a nested folder hierarchy with breadcrumb navigation in FlutterFlow
  • How to implement document version history with automatic version numbering
  • How to set up per-document access control with viewer and editor roles
  • How to add PDF preview and tag-based search functionality
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read30-40 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build a document management system with Firestore collections for documents and folders supporting nested hierarchy. Each document tracks versions so every edit creates a new entry while keeping all previous versions accessible. Implement access control with per-document viewer and editor lists. Add PDF preview via a Custom Widget, tag-based search, and breadcrumb navigation for deep folder structures. Upload files through FlutterFlowUploadButton to Firebase Storage.

Building a Secure Document Library with Folders, Versions, and Permissions

Managing documents requires more than basic file storage. This tutorial builds a full document management system with nested folders, automatic version tracking on every upload, per-document access control for viewers and editors, inline PDF preview, and tag-based search. It is suited for teams that need organized, permissioned, and auditable file management.

Prerequisites

  • A FlutterFlow project with Firestore, Firebase Storage, and authentication configured
  • Firebase Storage bucket with sufficient quota for document uploads
  • Basic familiarity with FlutterFlow Backend Queries and Action Flows

Step-by-step guide

1

Design the Firestore data model for documents and folders

Create a folders collection with fields: name (String), parentFolderId (String, nullable for root folders), createdBy (String), createdAt (Timestamp), depth (Integer, 0 for root). Create a documents collection: title (String), fileUrl (String), mimeType (String: 'application/pdf', 'image/png', etc.), size (Integer, bytes), uploadedBy (String), folderId (String), tags (String Array), version (Integer), accessControl (Map: {viewerIds: [String], editorIds: [String]}), createdAt (Timestamp), updatedAt (Timestamp). The depth field enables proper indentation in the folder tree display.

Expected result: Firestore has folders with parent references for nesting and documents with version numbers, tags, and access control maps.

2

Build the folder tree view with breadcrumb navigation

Create a DocumentsPage with a Page State variable currentFolderId (String, nullable, null for root). At the top, add a breadcrumb Row. Build the breadcrumb by walking up the parentFolderId chain from the current folder to root, then reversing the list. Each breadcrumb segment is a tappable Text widget that sets currentFolderId to that folder's ID. Display: Home > Projects > 2026 > Q1 with '>' separators. Below the breadcrumbs, add a ListView with two Backend Queries: one for folders where parentFolderId equals currentFolderId, and one for documents where folderId equals currentFolderId. Folders show with a folder icon and tapping them updates currentFolderId. Documents show with a file type icon.

Expected result: A folder tree view with breadcrumbs at top. Users navigate into folders and use breadcrumbs to jump back to any ancestor level.

3

Implement document upload with automatic version tracking

Add a FlutterFlowUploadButton in the DocumentsPage toolbar. On upload complete, query existing documents in the current folder with the same title. If a document with that title exists, create a new document with version set to the highest existing version plus one. If no document exists with that name, create a new document with version 1. Always create a new document rather than updating the existing one so that all previous versions remain accessible. Store the file in Firebase Storage under documents/{folderId}/{filename}_v{version}. Add a Version History button on each document row that opens a BottomSheet listing all versions of that document ordered by version descending.

Expected result: Every file upload creates a new version document. Users access version history to view or download any previous version.

4

Set up per-document access control with viewer and editor roles

On the document detail page, add a Permissions section visible only to the document owner (uploadedBy equals current user) or users in editorIds. Display two sections: Editors and Viewers. Each section shows a ListView of user names from the respective ID arrays. Add an Add User button that opens a search dialog to find users by name or email. When adding a user, update the accessControl map to add their UID to viewerIds or editorIds. For Firestore Security Rules, create rules that allow read access when the user's UID is in viewerIds or editorIds, and write access only when in editorIds or is the uploadedBy user. In the FlutterFlow UI, filter document queries to only return documents where the current user is in viewerIds, editorIds, or is the uploadedBy user.

Expected result: Document owners assign viewer and editor roles per document. Users only see documents they have been granted access to.

5

Add PDF preview and file type detection

Create a DocumentPreviewPage that receives documentId as a Route Parameter. Query the document and check the mimeType field. For PDFs (application/pdf), display a Custom Widget using the flutter_pdfview package that renders the PDF inline. For images (image/*), display a standard Image widget with the fileUrl. For all other types (docx, xlsx, etc.), show a Container with the file icon, file name, size, and a Download button that launches the fileUrl. The Custom Widget for PDF takes the fileUrl as a parameter and renders pages with swipe navigation.

pdf_preview_widget.dart
1// Custom Widget: PdfPreviewWidget
2import 'package:flutter/material.dart';
3import 'package:flutter_pdfview/flutter_pdfview.dart';
4import 'package:http/http.dart' as http;
5import 'dart:io';
6import 'package:path_provider/path_provider.dart';
7
8class PdfPreviewWidget extends StatefulWidget {
9 final String pdfUrl;
10 final double width;
11 final double height;
12 const PdfPreviewWidget({
13 super.key,
14 required this.pdfUrl,
15 required this.width,
16 required this.height,
17 });
18
19 @override
20 State<PdfPreviewWidget> createState() => _PdfPreviewWidgetState();
21}
22
23class _PdfPreviewWidgetState extends State<PdfPreviewWidget> {
24 String? _localPath;
25 bool _loading = true;
26
27 @override
28 void initState() {
29 super.initState();
30 _downloadPdf();
31 }
32
33 Future<void> _downloadPdf() async {
34 final response = await http.get(Uri.parse(widget.pdfUrl));
35 final dir = await getTemporaryDirectory();
36 final file = File('${dir.path}/preview.pdf');
37 await file.writeAsBytes(response.bodyBytes);
38 setState(() {
39 _localPath = file.path;
40 _loading = false;
41 });
42 }
43
44 @override
45 Widget build(BuildContext context) {
46 if (_loading) {
47 return const Center(child: CircularProgressIndicator());
48 }
49 return SizedBox(
50 width: widget.width,
51 height: widget.height,
52 child: PDFView(filePath: _localPath!),
53 );
54 }
55}

Expected result: PDFs render inline in the app. Images display directly. Other file types show a download option with file metadata.

6

Implement tag-based search across all accessible documents

Add a SearchPage with a TextField for text search and ChoiceChips for tag filters. Query documents where the current user has access (is in viewerIds, editorIds, or is uploadedBy). Filter by title containing the search term using a Firestore query with >= and < range operators on the title field. For tag filtering, use array-contains-any on the tags field with the selected tags. Display results in a ListView showing document title, folder path, tags as colored chips, version number, and last updated date. Tapping a result navigates to the DocumentPreviewPage.

Expected result: Users search documents by title text or filter by tags, seeing only documents they have permission to access.

Complete working example

FlutterFlow Document Management Setup
1FIRESTORE DATA MODEL:
2 folders/{folderId}
3 name: String
4 parentFolderId: String (nullable, null = root)
5 createdBy: String
6 createdAt: Timestamp
7 depth: Integer (0 = root)
8
9 documents/{documentId}
10 title: String
11 fileUrl: String (Firebase Storage)
12 mimeType: String
13 size: Integer (bytes)
14 uploadedBy: String
15 folderId: String
16 tags: ['contract', 'legal', '2026']
17 version: Integer
18 accessControl: {
19 viewerIds: [String],
20 editorIds: [String]
21 }
22 createdAt: Timestamp
23 updatedAt: Timestamp
24
25PAGE: DocumentsPage
26 Column
27 Row (Breadcrumbs: Home > Folder > Subfolder)
28 Each segment tappable sets currentFolderId
29 FlutterFlowUploadButton (toolbar)
30 ListView
31 Section 1: Folders (parentFolderId == currentFolderId)
32 Row: folder icon + name tap sets currentFolderId
33 Section 2: Documents (folderId == currentFolderId)
34 Row: file type icon + title + version badge + size + date
35 Tap DocumentPreviewPage
36 Long press Permissions / Version History
37
38PAGE: DocumentPreviewPage (Route: documentId)
39 Column
40 If mimeType == 'application/pdf':
41 Custom Widget: PdfPreviewWidget(pdfUrl)
42 If mimeType starts with 'image/':
43 Image(fileUrl)
44 Else:
45 Container (icon + filename + size + Download button)
46
47VERSION TRACKING:
48 On upload: query docs with same title in folder
49 If exists: new doc with version = max(existing) + 1
50 If new: version = 1
51 Storage path: documents/{folderId}/{title}_v{version}
52
53ACCESS CONTROL:
54 Read: uid in viewerIds OR editorIds OR == uploadedBy
55 Write: uid in editorIds OR == uploadedBy
56 Firestore Rules enforce the same logic server-side

Common mistakes when creating a Secure Document Management System in FlutterFlow

Why it's a problem: Building deep folder nesting without breadcrumb navigation

How to avoid: Add a breadcrumb Row at the top showing the full path (Home > Projects > 2026 > Q1) with tappable segments for instant navigation to any level.

Why it's a problem: Overwriting files instead of creating new versions on upload

How to avoid: Create a new document record with an incremented version number for every upload. Store each file at a unique Storage path including the version number.

Why it's a problem: Relying only on FlutterFlow UI filtering for access control

How to avoid: Implement Firestore Security Rules that check the accessControl map server-side in addition to filtering queries in the FlutterFlow UI.

Best practices

  • Always create new version documents on upload rather than overwriting existing files
  • Implement both UI-level and Firestore Security Rules-level access control
  • Add breadcrumb navigation for any folder hierarchy deeper than 2 levels
  • Show file type icons based on mimeType for quick visual identification
  • Store file metadata (size, type, uploader) in Firestore for fast listing without Storage API calls
  • Limit folder nesting depth to 5 levels to keep navigation manageable
  • Use tags for cross-folder document organization and search

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a secure document management system in FlutterFlow with nested folders, version history on every upload, per-document viewer/editor access control, inline PDF preview, and tag-based search. Show me the Firestore data model, breadcrumb navigation logic, version tracking approach, and access control implementation.

FlutterFlow Prompt

Create a documents page with a row of breadcrumb text links at the top, an upload button, and a list view below showing folder rows and document rows. Each document row has a file icon, title, version number badge, and date.

Frequently asked questions

Can I preview Microsoft Office files like .docx and .xlsx inline?

Not natively in FlutterFlow. For Office files, you can use a WebView widget loading Google Docs Viewer (docs.google.com/viewer?url=YOUR_FILE_URL) or convert files to PDF via a Cloud Function before storing.

How do I handle very large files like videos or CAD drawings?

Firebase Storage supports files up to 5TB. For files over 10MB, use resumable uploads in a Custom Action with a progress indicator. Consider compressing files or generating preview thumbnails before upload.

Can I add full-text search across document contents?

Firestore does not support full-text search natively. Use a Cloud Function to extract text from uploaded PDFs via a library like pdf-parse, then index the text in Algolia or Elasticsearch for full-text search.

How do I audit who accessed or modified a document?

Create an audit_log collection that records every access and modification event with userId, documentId, action (view, edit, download, share), and timestamp. Display the audit trail in the document detail page.

Can multiple users edit the same document simultaneously?

FlutterFlow does not support real-time collaborative editing. Use a checkout system where a user locks the document for editing and others see a 'Currently being edited by X' message until the lock is released.

Can RapidDev help build an enterprise document management system?

Yes. RapidDev can implement advanced features like OCR text extraction, full-text search, automated retention policies, digital signatures, compliance workflows, and integration with existing enterprise systems.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.