Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nayalsaurav/Storx/llms.txt

Use this file to discover all available pages before exploring further.

Storx supports arbitrarily deep folder hierarchies. You can create folders inside other folders, navigate into them via click, and jump back up the tree at any level using the breadcrumb bar in the header. Folders share the same files table as regular files, distinguished only by the isFolder flag.

Creating Folders

Folders are created from the CreateFolderDialog component rendered inside ActionBar. Submitting the dialog calls useFileOperations.createFolder(), which sends a POST request to /api/folders/create:
// hooks/useFileOperations.ts
const createFolder = async (name: string, parentId: string | null) => {
  if (!name.trim()) return false;

  const response = await fetch("/api/folders/create", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      name,
      userId,
      parentId,
    }),
  });
  // ...
};
Request body:
{
  "name": "Project Assets",
  "userId": "user_2abc123",
  "parentId": "550e8400-e29b-41d4-a716-446655440000"
}
Set parentId to null (or omit it) to create a folder at the root level. Server-side validation rules:
  • name must be a non-empty string — name.trim() === "" returns 400 folder name is required
  • If parentId is provided, the referenced folder must exist, belong to the authenticated user, and have isFolder = true — otherwise the server returns 404 Parent folder not found
On success, the server returns:
{
  "success": true,
  "message": "folder created successfully",
  "folder": { "...FileItem fields..." }
}
After a successful creation the dashboard calls fetchFiles(currentFolder) and fetchStorageInfo() to refresh the view.

Nested Structure

The files table uses a self-referential parentId foreign key to model the tree hierarchy:
// lib/db/schema.ts
export const files = pgTable("files", {
  id: uuid("id").defaultRandom().primaryKey(),
  name: text("name").notNull(),
  // ...
  parentId: uuid("parent_id"), // null for root-level items
  isFolder: boolean("is_folder").default(false).notNull(),
  // ...
});

export const fileRelation = relations(files, ({ one, many }) => ({
  parent: one(files, {
    fields: [files.parentId],
    references: [files.id],
    relationName: "parent",
  }),
  children: many(files, {
    relationName: "parent",
  }),
}));
  • Root items have parentId = null. The GET /api/files endpoint uses isNull(files.parentId) to fetch them when no parentId query parameter is supplied.
  • Nested items have parentId set to the UUID of their containing folder. The endpoint filters with eq(files.parentId, parentId) when the query parameter is present.
There is no enforced depth limit — you can nest folders as deeply as needed. useDashboardState manages the current folder context and the breadcrumb trail:
// hooks/useDashboardState.ts
const navigateToFolder = (folderId: string, folderName: string) => {
  setCurrentFolder(folderId);
  setBreadcrumbs((prev) => [...prev, { id: folderId, name: folderName }]);
};

const navigateToBreadcrumb = (index: number) => {
  const newBreadcrumbs = breadcrumbs.slice(0, index + 1);
  const targetFolder = newBreadcrumbs[newBreadcrumbs.length - 1];
  setBreadcrumbs(newBreadcrumbs);
  setCurrentFolder(targetFolder.id);
};
The Breadcrumb interface:
// types/types.d.ts
export interface Breadcrumb {
  id: string | null; // null for the Home root
  name: string;
}
The breadcrumb array is always initialised with a Home entry:
const [breadcrumbs, setBreadcrumbs] = useState<Breadcrumb[]>([
  { id: null, name: "Home" },
]);
Navigating into a folder appends a new breadcrumb entry. Clicking any breadcrumb item (including Home) calls navigateToBreadcrumb(index), which trims the array back to that position and sets currentFolder to its id. The Home button in Sidebar is wired to navigateToBreadcrumb(0), which always resets to the root:
// components/dashboard/Sidebar.tsx
<Button onClick={() => navigateToBreadcrumb(0)}>
  <Home className="w-4 h-4 mr-3" />
  Home
</Button>

Folder vs File

Both files and folders are rows in the single files table. The isFolder boolean column is the only distinction:
ColumnFileFolder
isFolderfalsetrue
sizeActual byte count0
typeMIME type (e.g. image/png)"folder"
fileUrlImageKit CDN URL"" (empty string)
imagekitFileIdImageKit file IDnull
In FileGrid and FileList, clicking a folder triggers onFolderClick(file.id, file.name) to navigate into it. Clicking a file has no default navigation action — use the action menu to download or manage it.
Moving files between folders is not yet supported. If you need a file in a different folder, delete the original and re-upload it to the target folder. The parentId of an existing record is not updated by any current API endpoint.

Build docs developers (and LLMs) love