-
-
Drop in product photos, pick a saved brand background, and the agent handles cutout, data extraction and categorization.
-
Catalog workspace: desktop and mobile preview, per-product visibility, public share link, and export to JSON, PDF or a ZIP of images.
-
The published catalog as customers see it: searchable, grouped by categories the agent assigned across the whole batch.
-
Slide to compare the original phone photo with the result. Fields come from the packaging — unreadable ones say so instead of guessing.
Inspiration
A corner shop with 200 products can't afford a photographer or a cataloguer. So the photos get taken on a phone, on the kitchen table, each one with a different background — and the catalog never gets published, or it gets published looking improvised.
The gap isn't talent or effort. It's that every tool for this assumes you already have a studio, a product database, and someone whose job is data entry. We wanted the version that works with what a shopkeeper actually has: a phone, a stack of products, and twenty minutes.
What it does
You upload photos of your products and pick a background you saved once. SnapFlick does the rest:
- Cuts out the product and drops the original background.
- Composes it on your brand background — auto-cropped, centered, scaled, with a soft shadow.
- Reads the packaging with a multimodal model and extracts name, brand, size, description, ingredients and barcode.
- Categorizes the whole batch at once — not product by product, which is what produces "Drinks", "Drink" and "Sodas" as three different categories in every naive implementation.
- Generate the catalog Generates catalogs in PDF format and offers the possibility of sharing a link without needing to provide a document that may be too large to share.
One design decision we're proud of: the agent never invents data. If the brand isn't
legible, the field comes back null with a confidence flag and a note saying what couldn't be
read and why. A catalog with three honest blanks is more useful to a shop owner than one with
three plausible fabrications they'll only discover after publishing.
How we built it
Three specialized agents on the Strands Agents SDK, coordinated by an orchestrator:
- VisionAgent — reads the packaging and returns a validated
ProductSheetvia Strands' structured output, so the model returns a typed Pydantic object instead of free text we'd have to parse. This eliminated an entire class of bug before it existed. - CatalogAgent — receives the full batch and produces one coherent taxonomy, seeded with a retail category list it can extend but not ignore.
- Orchestrator — runs the pipeline and isolates failures so one bad photo can't sink a batch.
The image work is deliberately not the model's job: rembg and Pillow handle cutout,
auto-crop and composition. They're deterministic, they're free, and they run on CPU — no reason
to spend tokens or latency on something a library does better.
Stack: Python 3.11, FastAPI, Pydantic, rembg + Pillow, Jinja2 for catalog rendering,
Next.js for the frontend. On AWS: S3 for images, catalogs and job state; ECR + ECS Express Mode
(Fargate) for the API container; Amplify Hosting for the frontend. The container is multi-arch
(amd64 + arm64) and implements the Bedrock AgentCore contract — /invocations and /ping on
port 8080.
Challenges we ran into
Amazon Bedrock was unusable for us — twice over. We're building from Venezuela, and
Anthropic models are geo-blocked here: every call returned Access to Anthropic models is not
allowed from unsupported countries. We switched to Amazon Nova and hit a second wall — a brand
new account with Bedrock quotas provisioned at zero, throttling the very first request ever made,
across multiple regions and providers. We opened a support case and kept building.
That forced the best architectural decision in the project: the model provider is a runtime choice, not a dependency. A factory returns Bedrock or Gemini from one environment variable; the agents never know which is behind them. We shipped on Gemini. If the Bedrock quota clears, it's a one-line change — and the AgentCore path is already built.
AWS App Runner was deprecated mid-project. We'd designed the deployment around it, then found it had closed to new customers — which included our account, created weeks earlier. We migrated to ECS Express Mode. That surfaced a cost trap worth knowing: unlike App Runner, the auto-created load balancer bills hourly whether or not anything is running, so "scale to zero" doesn't mean "pay zero."
The free-tier rate limits. Running on a free model tier during development means hitting per-minute caps constantly. We added exponential backoff on rate-limit errors and a content-hash cache for extractions — keyed on the image hash plus the model id and prompt version, so editing a prompt doesn't silently serve stale results. That cache is also why we can rerun the demo as many times as we want without burning quota.
Architecture mismatch. Our Dockerfile pinned ARM64 for AgentCore; ECS needed x86_64. An ARM image deploys "successfully" and then dies with an error that never mentions architecture. Multi-arch builds solved it permanently.
Accomplishments that we're proud of
Shipping a working, deployed product while the two AWS services we'd planned around became unavailable to us — one for geographic reasons, one for deprecation. The provider-agnostic design wasn't foresight; it was a response to being blocked, and it made the project stronger.
And the honesty constraint. It would have been easier to let the model guess.
What we learned
Structured output is worth adopting on day one. Deterministic work belongs in libraries, not in prompts. And infrastructure decisions have expiry dates — verify that a service still accepts new customers before you build a plan around it.
What's next for SnapFlick
Export to WhatsApp Business catalog and Shopify CSV. Manual correction of extracted fields from the frontend. Barcode lookup against public product databases. And a Spanish-first onboarding, because the shops we built this for aren't reading English documentation.
Built With
- amazon-bedrock-agentcore
- amazon-ecs
- amazon-web-services
- aws-amplify
- cloudformation
- fastapi
- google-gemini
- jinja
- next.js
- pillow
- pydantic
- python
- react
- rembg
- sqlite
- strands-agents
- tailwindcss
- typescript
- uvicorn
Log in or sign up for Devpost to join the conversation.