Features
File storage your apps can share
Connect storage-service to upload, browse, and share files across your apps. Use the software development kit (SDK) for file operations and the Files app for browsing and selection. Manage access and storage limits at the company level.
Connect your apps to a shared file store
The storage-service backend stores files in Amazon S3-compatible storage or on your server's filesystem. It verifies the signed-in account and enforces company and optional per-user storage limits.
Your apps call shellui.storage through the SDK. The shell sends each request to the configured storage service with the signed-in account's access token.
1. Connect storage
Set storage.url to your storage service. Add filesUrl to connect the Files explorer and picker.
2. Check storage usage
See current usage in Settings → Storage. You can hide this settings page while keeping storage available in Administration and through the SDK.
3. Work with files
After init, upload, list, move, and download through shellui.storage.from("company").
{
"storage": {
"url": "http://localhost:8001",
"filesUrl": "http://localhost:5175/"
}
}Upload and select files from your app
Use the SDK to upload, list, move, and download files. Calls return { data, error } so your app can handle failures. The file picker opens the Files app in a shell modal for selecting files or folders.
import { shellui } from "@shellui/sdk";
await shellui.init();
const bucket = shellui.storage.from("company");
const file = new File(["quarter one"], "q1.pdf", { type: "application/pdf" });
const { data, error } = await bucket.upload(
"docs/reports/2024/q1.pdf",
file,
{ upsert: true },
);import { shellui } from "@shellui/sdk";
await shellui.init();
const { data: entries, error } = await shellui.storage
.from("company")
.list("docs/reports", {
limit: 200,
sortBy: { column: "name", order: "asc" },
});import { shellui } from "@shellui/sdk";
await shellui.init();
const { data: blob, error } = await shellui.storage
.from("company")
.download("docs/reports/2024/q1.pdf");
if (!error) {
const url = URL.createObjectURL(blob);
}import { shellui } from "@shellui/sdk";
await shellui.init();
const result = await shellui.selectFiles({ multiple: true });
if (!result) return;
for (const file of result.items) {
console.log(file.id, file.path);
}Control who can access each file
Each company has a file collection, or bucket, named company. New items at the root are private to their creator; items inside folders inherit the folder's permissions. Share selected files and folders with members, or create a share link for someone outside the company.
Access grants
Grant or deny read, write, or administration access to a file or folder. Apply permissions to individual accounts or the whole company.
Share links
Share an individual file with a link that needs no account. Set an expiry, a download limit, or both, and revoke the link when access is no longer needed.
Quotas
Set a total storage limit for the company and optional limits per account. The service rejects uploads that exceed those limits, and Settings shows current usage.
Events, webhooks, and email
When you set EMAIL_SERVICE_API_KEY, storage posts events to email-service and stores every event for the event log. Webhook and email bodies omit tokens, sign-in links, signed URLs, and other secrets. Company owners manage the rules in Administration.
The storage image runs webhook retries every minute and an hourly data purge. It does not need cron. In production, set REDIS_URL or the container does not start. Scheduler metrics stay on the staff metrics endpoint.
See how the architecture connects the shell to its backend services.