bradygaster/squad-places/binary-file-storage
- community
Checking that the SKILL.md file is still in the repository.
Pattern for storing and serving binary files (images, etc.) across both File and Blob storage backends
Install
npx vskill@latest install bradygaster/squad-places/binary-file-storageSKILL.md
Context
When adding binary file support (images, attachments) to Squad Places, both FileStorageService and BlobStorageService must be extended consistently. The pattern applies to any new binary content type.
Patterns
Storage Interface
Add Save{Type}Async(Guid ownerId, Guid id, byte[] data, string contentType) and Get{Type}Async(Guid ownerId, Guid id) returning (byte[] Data, string ContentType)? to IBlobStorageService. Owner-scoped IDs enable natural data isolation.
FileStorageService
- Store binary at
{basePath}/{type}/{ownerId}/{id}{extension} - Store content type in a
.metasidecar file at{basePath}/{type}/{ownerId}/{id}.meta - Map content types to extensions in a switch expression
- Create the top-level directory in
InitializeAsync(); owner subdirectories created on-demand viaDirectory.CreateDirectory()
BlobStorageService
- Use a dedicated container (e.g.,
images) - Blob path:
{ownerId}/{id}{extension}— virtual folder structure - Set
BlobHttpHeaders.ContentTypeon upload - For retrieval, search by prefix with
GetBlobsAsync(BlobTraits, BlobStates, prefix, CancellationToken) - Create container in
InitializeAsync()
API Pattern
POST /api/{type}— accept base64 body with owner ID, validate owner exists, store, return relative URLGET /api/{type}/{ownerId}/{id}— serve withResults.File(data, contentType)- Inline upload on parent entity (e.g.,
ImageDataonPublishArtifactRequest) as convenience - Only relative URLs — reject absolute http/https URLs to prevent SSRF and ensure all content is hosted
URL Security
- Validate URLs with regex matching
/api/{type}/{guid}/{guid}format - In HTML sanitizer, use
FilterUrlevent to strip non-relativesrcattributes rather than removing the tag entirely - This is more surgical than scheme-based allowlisting — permits relative paths without custom schemes
Dockerfile
Add the new data directory to the mkdir -p line.
Examples
See src/SquadPlaces.Data/FileStorageService.cs (SaveImageAsync/GetImageAsync) and src/SquadPlaces.Web/Api/ApiEndpoints.cs (image endpoints).
Anti-Patterns
- Don't store binary data as base64 in JSON — decode to bytes first
- Don't use
GetBlobsAsync(prefix:)named parameter — the .NET 10 API requires positional args - Don't forget the
.metasidecar in file storage — without it, you can't serve with correct Content-Type
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.squad/skills/binary-file-storage/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/bradygaster/squad-places/binary-file-storage)