Skip to main content
RapidDev - Software Development Agency
firebase-tutorial

How to Organize Folders and File Paths in Firebase Storage

Firebase Storage uses virtual folders created by forward slashes in file paths — there are no actual folder objects. Upload files to paths like users/{uid}/avatars/photo.jpg to create a logical hierarchy. Use listAll() and list() to browse folder contents, and write security rules that match path segments to control access per folder. This pattern keeps files organized and security rules manageable as your app grows.

What you'll learn

  • How Firebase Storage virtual folders work with path prefixes
  • How to upload files into organized folder structures using the modular SDK
  • How to list folder contents using listAll() and paginated list()
  • How to write security rules scoped to specific folder paths
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate9 min read15-20 minFirebase Storage (Spark and Blaze plans), firebase/storage v9+ modular SDKMarch 2026RapidDev Engineering Team
TL;DR

Firebase Storage uses virtual folders created by forward slashes in file paths — there are no actual folder objects. Upload files to paths like users/{uid}/avatars/photo.jpg to create a logical hierarchy. Use listAll() and list() to browse folder contents, and write security rules that match path segments to control access per folder. This pattern keeps files organized and security rules manageable as your app grows.

Structuring Files With Virtual Folders in Firebase Storage

Firebase Storage is a flat object store — it has no real directory hierarchy. Folders are created implicitly by including forward slashes in file paths. The path users/abc123/avatar.jpg creates the appearance of a users folder containing an abc123 folder. This tutorial covers how to design a folder structure, upload files to specific paths, list folder contents, and write security rules that restrict access based on folder paths.

Prerequisites

  • A Firebase project with Storage enabled in the Firebase Console
  • Firebase JS SDK installed and initialized in your web app
  • A Storage bucket created (default bucket is included with every project)
  • Basic understanding of Firebase Authentication for user-scoped paths

Step-by-step guide

1

Design a folder structure for your app

Plan your folder structure before uploading files. A common pattern uses the authenticated user's UID as a top-level folder, with subfolders for different file types. For shared content, use a public or shared folder at the root level. Keep paths short and consistent — they become part of your security rules and download URLs.

typescript
1// Recommended folder structures:
2
3// User-scoped files
4// users/{uid}/avatar/profile.jpg
5// users/{uid}/documents/resume.pdf
6// users/{uid}/uploads/photo-001.jpg
7
8// Shared/public content
9// public/banners/hero.jpg
10// public/icons/logo.svg
11
12// Team/org-scoped files
13// teams/{teamId}/assets/logo.png
14// teams/{teamId}/documents/contract.pdf
15
16// Timestamped uploads for uniqueness
17// users/{uid}/photos/{timestamp}-{filename}

Expected result: You have a documented folder structure that maps to your app's data model and supports your security requirements.

2

Upload files to specific folder paths

Use the ref() function with a full path string to place files in the correct folder. The folder is created automatically when the first file is uploaded to that path. You do not need to create folders in advance. Set custom metadata on uploads to track file type, uploader, or other attributes that help with organization.

typescript
1import { getStorage, ref, uploadBytes, uploadBytesResumable } from "firebase/storage";
2import { getAuth } from "firebase/auth";
3
4const storage = getStorage();
5const auth = getAuth();
6
7async function uploadUserFile(
8 file: File,
9 subfolder: string
10): Promise<string> {
11 const user = auth.currentUser;
12 if (!user) throw new Error("Must be logged in to upload");
13
14 // Build the path: users/{uid}/{subfolder}/{filename}
15 const timestamp = Date.now();
16 const safeName = file.name.replace(/[^a-zA-Z0-9.-]/g, "_");
17 const filePath = `users/${user.uid}/${subfolder}/${timestamp}-${safeName}`;
18
19 const storageRef = ref(storage, filePath);
20 const metadata = {
21 customMetadata: {
22 uploadedBy: user.uid,
23 originalName: file.name,
24 },
25 };
26
27 await uploadBytes(storageRef, file, metadata);
28 return filePath;
29}
30
31// Usage
32// uploadUserFile(selectedFile, "documents");

Expected result: Files are uploaded to structured paths like users/abc123/documents/1711612800000-report.pdf with custom metadata.

3

List files in a folder using listAll() and list()

Use listAll() to get every item and subfolder in a path, or use list() with maxResults for paginated results. The listAll() function returns a ListResult with items (files) and prefixes (subfolders). For folders with many files, use list() with pagination to avoid loading everything at once. Both functions only list direct children — they do not recurse into subfolders.

typescript
1import { getStorage, ref, listAll, list, getDownloadURL } from "firebase/storage";
2
3const storage = getStorage();
4
5// List all files in a folder
6async function listFolder(folderPath: string) {
7 const folderRef = ref(storage, folderPath);
8 const result = await listAll(folderRef);
9
10 // Files in this folder
11 for (const item of result.items) {
12 const url = await getDownloadURL(item);
13 console.log(`File: ${item.name}, URL: ${url}`);
14 }
15
16 // Subfolders
17 for (const prefix of result.prefixes) {
18 console.log(`Subfolder: ${prefix.name}`);
19 }
20}
21
22// Paginated listing for large folders
23async function listFolderPaginated(
24 folderPath: string,
25 pageSize: number = 20
26) {
27 const folderRef = ref(storage, folderPath);
28 let pageToken: string | undefined;
29 const allItems = [];
30
31 do {
32 const result = await list(folderRef, {
33 maxResults: pageSize,
34 pageToken,
35 });
36 allItems.push(...result.items);
37 pageToken = result.nextPageToken;
38 } while (pageToken);
39
40 return allItems;
41}

Expected result: You can browse folder contents, display file lists in your UI, and navigate subfolders programmatically.

4

Write security rules scoped to folder paths

Firebase Storage security rules use path matching with wildcards. Match path segments to restrict access to specific folders. The most common pattern uses {userId} as a wildcard that must match request.auth.uid, ensuring users can only access their own folder. Always validate content type and file size in rules to prevent abuse.

typescript
1// storage.rules
2rules_version = '2';
3service firebase.storage {
4 match /b/{bucket}/o {
5
6 // User-scoped files: only the owner can read/write
7 match /users/{userId}/{allPaths=**} {
8 allow read, write: if request.auth != null
9 && request.auth.uid == userId;
10 }
11
12 // User avatars: anyone can read, only owner can write
13 match /users/{userId}/avatar/{fileName} {
14 allow read: if true;
15 allow write: if request.auth != null
16 && request.auth.uid == userId
17 && request.resource.size < 5 * 1024 * 1024
18 && request.resource.contentType.matches('image/.*');
19 }
20
21 // Public folder: anyone can read, no one can write via client
22 match /public/{allPaths=**} {
23 allow read: if true;
24 allow write: if false;
25 }
26
27 // Team files: only team members can access
28 match /teams/{teamId}/{allPaths=**} {
29 allow read, write: if request.auth != null
30 && request.auth.token.teamId == teamId;
31 }
32 }
33}

Expected result: Security rules enforce folder-level access control — users can only read and write files in their own folders.

5

Delete all files in a folder

Firebase Storage has no built-in delete folder operation. To delete a folder and all its contents, list all files in the folder and delete each one individually. For large folders, use the paginated list() approach and delete in batches. This is a common operation when users delete their account or when cleaning up temporary uploads.

typescript
1import { getStorage, ref, listAll, deleteObject } from "firebase/storage";
2
3const storage = getStorage();
4
5async function deleteFolder(folderPath: string): Promise<number> {
6 const folderRef = ref(storage, folderPath);
7 const result = await listAll(folderRef);
8 let deletedCount = 0;
9
10 // Delete all files in this folder
11 const deletePromises = result.items.map(async (itemRef) => {
12 await deleteObject(itemRef);
13 deletedCount++;
14 });
15
16 // Recursively delete subfolders
17 const subfolderPromises = result.prefixes.map((prefix) =>
18 deleteFolder(prefix.fullPath)
19 );
20
21 await Promise.all([...deletePromises, ...subfolderPromises]);
22
23 for (const subfolder of subfolderPromises) {
24 deletedCount += await subfolder;
25 }
26
27 return deletedCount;
28}
29
30// Usage: deleteFolder(`users/${userId}`);

Expected result: All files within the specified folder path are deleted, including files in nested subfolders.

Complete working example

storage-folders.ts
1// Firebase Storage — Folder Organization Utilities
2import { initializeApp } from "firebase/app";
3import {
4 getStorage,
5 ref,
6 uploadBytes,
7 listAll,
8 list,
9 getDownloadURL,
10 deleteObject,
11 getMetadata,
12} from "firebase/storage";
13import { getAuth } from "firebase/auth";
14
15const app = initializeApp({ /* your config */ });
16const storage = getStorage(app);
17const auth = getAuth(app);
18
19// Upload a file to a user-scoped folder
20export async function uploadToFolder(
21 file: File,
22 folder: string
23): Promise<{ path: string; url: string }> {
24 const user = auth.currentUser;
25 if (!user) throw new Error("Authentication required");
26
27 const safeName = file.name.replace(/[^a-zA-Z0-9.-]/g, "_");
28 const path = `users/${user.uid}/${folder}/${Date.now()}-${safeName}`;
29 const fileRef = ref(storage, path);
30
31 await uploadBytes(fileRef, file, {
32 customMetadata: { uploadedBy: user.uid },
33 });
34
35 const url = await getDownloadURL(fileRef);
36 return { path, url };
37}
38
39// List all files in a folder with metadata
40export async function listFolderContents(folderPath: string) {
41 const folderRef = ref(storage, folderPath);
42 const result = await listAll(folderRef);
43
44 const files = await Promise.all(
45 result.items.map(async (itemRef) => {
46 const [url, metadata] = await Promise.all([
47 getDownloadURL(itemRef),
48 getMetadata(itemRef),
49 ]);
50 return {
51 name: itemRef.name,
52 fullPath: itemRef.fullPath,
53 url,
54 size: metadata.size,
55 contentType: metadata.contentType,
56 updated: metadata.updated,
57 };
58 })
59 );
60
61 const subfolders = result.prefixes.map((p) => ({
62 name: p.name,
63 fullPath: p.fullPath,
64 }));
65
66 return { files, subfolders };
67}
68
69// Paginated listing for large folders
70export async function listFolderPage(
71 folderPath: string,
72 pageSize: number = 20,
73 pageToken?: string
74) {
75 const folderRef = ref(storage, folderPath);
76 const result = await list(folderRef, { maxResults: pageSize, pageToken });
77 return {
78 items: result.items.map((i) => ({ name: i.name, path: i.fullPath })),
79 nextPageToken: result.nextPageToken,
80 };
81}
82
83// Recursively delete a folder and all contents
84export async function deleteFolder(folderPath: string): Promise<number> {
85 const folderRef = ref(storage, folderPath);
86 const result = await listAll(folderRef);
87 let count = 0;
88
89 await Promise.all(
90 result.items.map(async (item) => {
91 await deleteObject(item);
92 count++;
93 })
94 );
95
96 for (const prefix of result.prefixes) {
97 count += await deleteFolder(prefix.fullPath);
98 }
99
100 return count;
101}

Common mistakes when organizing Folders and File Paths in Firebase Storage

Why it's a problem: Trying to create an empty folder in Firebase Storage — folders only exist when they contain at least one file

How to avoid: Folders in Firebase Storage are virtual and created implicitly by file paths. You cannot create an empty folder. Upload a file to a path and the folder appears automatically.

Why it's a problem: Using listAll() on folders with thousands of files, causing memory issues and slow performance

How to avoid: Use list() with the maxResults option for paginated listing. Process files in pages of 20-100 items to keep memory usage manageable.

Why it's a problem: Not including the user's UID in the storage path, making it impossible to write ownership-based security rules

How to avoid: Always include request.auth.uid as a path segment (e.g., users/{uid}/...) so security rules can verify that the authenticated user owns the folder.

Why it's a problem: Forgetting to deploy updated security rules after changing the folder structure

How to avoid: Run firebase deploy --only storage after modifying storage.rules. Rules changes do not take effect until deployed.

Best practices

  • Include the user's UID as a top-level folder segment to enable ownership-based security rules
  • Use timestamps or UUIDs in filenames to prevent accidental overwrites of same-named files
  • Sanitize filenames by removing special characters before using them in storage paths
  • Use list() with pagination for folders that may contain more than 100 files
  • Write security rules that validate content type and file size in addition to authentication
  • Use a consistent naming convention for folders (lowercase, hyphens) across your app
  • Create a public folder with read-only rules for assets that should be accessible without authentication
  • Use Cloud Functions with the Admin SDK for bulk operations like folder deletion on large datasets

Still stuck?

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

ChatGPT Prompt

I need to organize files in Firebase Storage for a project management app. Each project has a team that uploads documents and images. Design a folder structure that supports user-scoped uploads, team-shared files, and public assets. Write TypeScript utility functions for uploading to a specific folder, listing folder contents with metadata, and deleting an entire folder recursively. Include Firebase Storage security rules.

Firebase Prompt

Create a Firebase Storage folder structure for my app with user-scoped paths (users/{uid}/avatars, users/{uid}/documents) and a public folder for shared assets. Write security rules so users can only access their own folders, avatars are publicly readable, and uploads are limited to 5 MB images. Include a TypeScript function that uploads a file to the correct folder path.

Frequently asked questions

Do folders actually exist in Firebase Storage?

No. Firebase Storage is a flat object store. Folders are virtual — they are created implicitly by the forward slashes in file paths. A file at users/abc/photo.jpg creates the appearance of a users folder and an abc subfolder, but no folder objects exist.

Can I rename or move a folder in Firebase Storage?

There is no rename or move operation. To move files, you must download each file and re-upload it to the new path, then delete the original. For large moves, use a Cloud Function with the Admin SDK.

What happens to a folder when I delete all files in it?

The folder disappears. Since folders are virtual and defined by file paths, a folder with no files simply does not exist. listAll() will not return it as a prefix.

How do I list only subfolders without listing files?

The listAll() and list() functions return both items (files) and prefixes (subfolders). To get only subfolders, use result.prefixes and ignore result.items.

Is there a limit to how many files I can have in one folder?

There is no limit on files per folder. However, listAll() loads all references into memory, so for folders with thousands of files, use the paginated list() function with maxResults to avoid performance issues.

Can I set different security rules for different folders?

Yes. Storage security rules use path matching with wildcards. You can write different rules for each folder path, such as allowing public read on /public/** while restricting /users/{userId}/** to the authenticated owner.

Can RapidDev help design my Firebase Storage folder structure?

Yes. RapidDev can design a storage architecture that matches your app's data model, write security rules for each folder path, and build utility functions for uploads, listings, and cleanup.

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.