Public Buckets
Mark a bucket public to serve its files at stable, edge-cached URLs through the Koolbase CDN. No signing, no expiry — paste a URL into an <img> tag, share it in an email, or embed it anywhere a browser can read.
How public buckets work
Files uploaded to a public bucket land in dedicated public storage backed by the Koolbase CDN. Each file gets a permanent URL at the Koolbase CDN domain, with the project ID, bucket name, and path forming the three segments:
https://cdn.koolbase.com/{project_id}/{bucket}/{path}That URL serves the file directly from a global edge network — no signing, no time-bound expiry, no round-trip to Koolbase's API on every read. The first request to a region warms the cache; subsequent requests are served from the edge.
When to use them
Public buckets fit anywhere you need a URL that can be:
- Embedded in HTML (
<img>,<video>,<audio>) - Linked from email, social media, marketing copy
- Cached at the edge for fast global delivery
- Read without authentication or signing
Common use cases:
- User profile photos and avatars
- Product images for an e-commerce app
- Marketing assets — banners, hero images, OG cards
- Public PDFs, brochures, downloadable installers
- Static fonts and webfont assets
Don't use public buckets for sensitive data
Creating a public bucket
In the dashboard:
- Open the project, navigate to Storage
- Click the + button next to Buckets
- Enter a bucket name
- Toggle Public Access on
- (Optional) Configure size limits and MIME type restrictions
- Click Create bucket
Public access is set at creation time
Getting the public URL
From the dashboard
- Open the public bucket from the Storage page
- Find the file row
- Click the copy icon (between Download and Delete)
- The URL is on your clipboard, ready to paste anywhere
From the SDK
The SDK's getDownloadUrl() method already returns the CDN URL for files in public buckets — no method change needed, no branching on bucket type.
final url = await Koolbase.storage.getDownloadUrl(
bucket: 'avatars',
path: 'user-123.png',
);
// For public bucket files, url is the CDN URL — long-lived,
// embeddable anywhere a browser can fetch. For private bucket
// files, url is a 1-hour presigned URL.
print(url);const { url } = await koolbase.storage.getDownloadUrl({
bucket: 'avatars',
path: 'user-123.png',
});
// For public bucket files, url is the CDN URL — long-lived,
// embeddable anywhere a browser can fetch. For private bucket
// files, url is a 1-hour presigned URL.
console.log(url);Building the URL in-app (Flutter v11.4+)
When you have a bucket and path but no object in hand — an image whose path comes out of a database record, for instance — build the CDN URL synchronously with publicUrlFor(). No network call, no projectId argument: the SDK learns its project identity from the bootstrap it already performs at startup.
final url = Koolbase.storage.publicUrlFor(
bucket: 'avatars',
path: record['avatar_path'],
// Optional edge resize — served transformed from the CDN:
transform: const KoolbaseImageTransform(width: 200, height: 200),
);
Image.network(url);It throws KoolbaseStorageProjectIdentityException (code project_identity_unavailable) only when the very first bootstrap has never completed — a fresh install starting offline. That state is transient and heals automatically once the device is online; it is deliberately distinct from KoolbaseObject.publicUrl returning null, which means the object lives in a private bucket and has no public URL at all.
Constructing URLs directly
For consumers outside the SDK — static site generation, server-side rendering, scripts — public bucket URLs follow a predictable pattern (inside a Flutter app, prefer publicUrlFor() above so URL topology stays the SDK's concern):
https://cdn.koolbase.com/{project_id}/{bucket}/{path}URL-encode each path segment individually (preserving the / separators) so spaces, parentheses, and other special characters don't corrupt the URL.
Embedding public files
Public bucket URLs work directly anywhere a browser fetches a URL:
<img src="https://cdn.koolbase.com/proj_abc/avatars/user-123.png" alt="User avatar" />
<video src="https://cdn.koolbase.com/proj_abc/videos/intro.mp4" controls />
<a href="https://cdn.koolbase.com/proj_abc/docs/manual.pdf">Download manual</a>.hero {
background-image: url('https://cdn.koolbase.com/proj_abc/marketing/hero.jpg');
}For programmatic fetch() calls from JavaScript on other origins, public buckets are CORS-configured to allow GET requests from any origin out of the box. Custom CORS rules for specific origins or methods can be added per-bucket if you need finer control.
Cache behavior
Public bucket responses are cached at the CDN edge per the standard caching policy. When you overwrite a file at the same path, the new bytes become immediately readable from origin requests, but cached edge copies may persist for some time before refreshing.
Bust the cache with a query string
cdn.koolbase.com/.../hero.jpg?v=2. The CDN treats each distinct query string as a different cache key, so updating the value forces a fresh fetch.Security considerations
Public bucket files are accessible to anyone with the URL. Path obscurity isn't a meaningful access control — assume URLs will eventually be shared, indexed, or guessed.
- Don't store secrets in public files — API keys, tokens, credentials, password hashes — including in custom metadata fields, which are also publicly readable
- Don't infer access permission from whether you've shared a URL; once a URL is out, it's out
- For user-private content, use a private bucket and serve via the SDK's
getDownloadUrl()— the returned presigned URL is short-lived and tied to whoever requested it - Treat public bucket URLs the same way you'd treat any other public web resource