Skip to content

Collectum: Building a Private Full-Stack AI Collection App

Collectum panel

Project Overview

Collectum is a private full-stack product I am building around a simple idea: use AI to identify real-world subjects from images and turn the confirmed results into a personal collection. The product direction is close to a "real-world Pokédex", but adapted to a broader set of topics such as animals, insects, plants, monuments and future custom categories.

The app is mobile-first. A user selects a topic, captures or uploads an image, sends it for AI analysis, reviews the result, and can save the completed analysis as a collection item. The long-term experience is collection-driven: browse discoveries by category, inspect details, search or filter items, and build a personal archive of things found in the real world.

The repository is private, so this article intentionally avoids exposing source code, private endpoints, deployment internals, secrets, or any implementation detail that would put the project at risk. The goal is to show the engineering scope, architecture and testing discipline behind the project without turning a private product into an open blueprint.

Product Direction

Collectum is built around four core product capabilities:

  • Image-based identification using AI.
  • Topic-based categorization.
  • A saved personal collection.
  • A credit model that keeps AI usage economically controlled.

The expected product loop is:

  1. Choose a topic.
  2. Capture or upload one or more images.
  3. Select the best image.
  4. Upload it to the backend.
  5. Create an analysis request.
  6. Wait while the backend processes it asynchronously.
  7. Review the AI-generated result.
  8. Save the result into the user's collection.

The project is also designed with monetization constraints in mind. AI calls have a real cost, so the backend validates and consumes credits before expensive analysis work starts. The model supports free monthly usage, subscription-style credit grants, and pay-as-you-go expansion later.

Mobile Experience

The frontend visual direction is a minimal fantasy card interface: modern mobile UI, naturalist collection, role-playing card inspiration, and a clear hierarchy that avoids becoming noisy or ornamental.

The current public-facing design assets include the welcome and login screens:

Collectum welcome screen

Collectum login screen

There is also a short video preview of the current mobile experience:

The app aims to feel lightly playful but still practical. Topic cards use illustrated headers and a card-like composition. The home screen is planned around a horizontal topic carousel and a central action button for starting an analysis. Collection browsing will later use a mobile grid, with item cards leading into detail screens.

Stack

Collectum is a pnpm monorepo with Turbo, Task and Husky automation.

The backend stack is:

  • Go.
  • Chi for HTTP routing.
  • PostgreSQL through pgx.
  • SQL migrations through golang-migrate.
  • S3-compatible image storage.
  • Qwen as the real AI provider.
  • Deterministic fake AI provider for local development and tests.
  • OpenAPI generation.
  • Async analysis workers.

The frontend stack is:

  • React Native.
  • Expo.
  • Expo Router.
  • TypeScript.
  • TanStack Query.
  • Zod.
  • i18next and react-i18next.
  • Expo Secure Store for session persistence.
  • Jest, jest-expo and React Native Testing Library.

The root tooling includes:

  • pnpm dev
  • pnpm build
  • pnpm test
  • pnpm test:integration
  • pnpm lint
  • pnpm openapi
  • pnpm check

The repository also includes local development manifests for PostgreSQL, OpenAPI docs, a local tools hub and a browser-based API client. Real environment files are intentionally excluded and guarded by repository checks.

Backend Architecture

The backend is organized as domain-oriented Go packages under backend/internal. The main domains are:

  • auth: registration, login, refresh, logout and auth sessions.
  • users: user profile and identity data.
  • credits: credit balances and credit transactions.
  • images: image validation, upload, preview generation and signed access.
  • analysis: AI analysis attempts, jobs and asynchronous processing.
  • collection: saved collection items created from completed analyses.
  • prompts: user/topic/language prompt templates.
  • ai: analyzer boundary, fake provider and Qwen provider.
  • ai_logs: audit trail for AI requests.
  • adapters: explicit bridges between domains.
  • platform: HTTP server, config, storage and database infrastructure.

This structure keeps the sensitive parts of the system separated. The analysis service does not own credit accounting. The collection service does not directly inspect arbitrary analysis attempts; it works through an analysis boundary that only exposes completed user-owned analysis. The AI provider is behind an analyzer interface, so local and integration tests can run in fake mode without real model credentials.

Analysis Workflow

The analysis flow is the core backend workflow.

When a user creates an analysis request, the backend:

  1. Validates the user, topic and image.
  2. Defaults language when needed.
  3. Starts a database transaction.
  4. Creates a queued analysis attempt.
  5. Consumes one user credit.
  6. Stores the credit transaction reference on the analysis attempt.
  7. Creates a queued analysis job.
  8. Commits the transaction.
  9. Notifies workers that new jobs are available.

This transaction is important. It prevents the system from creating an analysis attempt without consuming credits, or consuming credits without creating the job that will eventually process the request.

The worker then claims jobs, marks attempts as processing, retrieves the stored image, generates a short-lived signed URL, resolves the right prompt template, records an AI request log, calls the analyzer, and persists the final result or failure state. Workers can be triggered by PostgreSQL notifications and also poll on an interval, which makes the processing flow responsive without depending on a separate queue service at this stage.

The fake analyzer is a key engineering decision. It allows local development and integration tests to exercise the workflow without calling the real AI provider. The real Qwen integration remains available behind configuration, but tests force fake mode.

Credits and Cost Control

Collectum treats credits as a first-class domain because AI calls are not free.

The credit service supports:

  • Creating balances.
  • Granting credits.
  • Consuming credits.
  • Refunding credits.
  • Recording credit transactions.
  • Using row-level locking during balance changes.
  • Idempotent refund handling through references.

Each analysis request consumes credits before the AI call is made. Credit movements are recorded as transactions, not just balance updates, which makes later auditing possible. Signup currently grants initial credits through the auth registration flow, and prompt templates are created as part of onboarding.

This credit-first architecture protects both product economics and user experience. The backend can reject requests before expensive AI work starts, rather than discovering after the fact that the user had no available balance.

Image Pipeline

The image service validates uploaded files before storage. It checks ownership, size, MIME type, decodes the image, verifies minimum dimensions, derives the final content type, and generates both:

  • an original object,
  • a JPEG preview object.

Storage keys are organized under user and image identifiers. The service can later return the preview or original image, and it can generate a short-lived presigned URL for the AI analysis pipeline.

This separation between original and preview is useful for mobile performance. The app can show lightweight previews in lists and detail screens while preserving the original for analysis and inspection.

Collection Model

The collection domain stores completed AI analysis results as user-owned collection items.

When the user saves a result, the collection service:

  1. Validates ownership.
  2. Loads a completed analysis through the analysis boundary.
  3. Parses the AI result.
  4. Stores indexed summary fields such as common name, scientific name, category, description, safety notes, confidence and visible traits.
  5. Preserves the original result JSON.
  6. Prevents saving the same analysis attempt more than once.

This design gives the product two useful layers of data. The original AI response remains available for future improvements, while indexed fields make collection browsing and filtering easier.

Authentication and Sessions

The auth domain supports registration, login, refresh and logout. Registration is transactional: it creates the user, initializes credits, grants signup credits, creates default prompt templates and persists an auth session. Login validates credentials and active status. Refresh tokens are stored as hashes through session records, and logout revokes the corresponding session.

The mobile frontend stores refresh tokens through Expo Secure Store and keeps access-token state in an auth provider. Tests cover both login through the form and session restoration from a previously saved refresh token.

Frontend Architecture

The React Native frontend follows a feature-oriented architecture:

text
app/            Expo Router layouts and routes
src/domain/     Shared domain concepts
src/features/   Auth, app shell, home, analysis and future product features
src/shared/     API client, design tokens, UI primitives, errors and i18n
src/testing/    Test setup and utilities

The frontend avoids putting backend state into ad-hoc local stores. TanStack Query is intended as the main source of truth for server state: current user, topics, image uploads, analysis status polling and collection lists.

Zod is used at the API and form boundaries. It validates payloads and responses where runtime safety matters, without turning every internal object into a schema.

The design foundation includes:

  • color tokens,
  • spacing tokens,
  • radius tokens,
  • typography tokens,
  • shadows,
  • reusable UI primitives such as Screen, AppText, AppButton, AppTextInput and Card.

The frontend also includes internationalization support for English and Spanish, so product copy can evolve without being hard-coded into components.

Testing Strategy

Collectum has a layered testing strategy.

On the backend, tests cover:

  • domain services,
  • handlers,
  • repositories,
  • AI factory behavior,
  • Qwen integration boundaries,
  • credit logic,
  • image upload logic,
  • analysis worker behavior,
  • OpenAPI generation,
  • platform configuration,
  • full integration endpoint flows.

Integration tests use build tags and require a dedicated test database environment. They run migrations, reset tables, exercise endpoints and verify important side effects such as signup credits and default prompt creation. For storage-heavy flows, the test environment can use ephemeral S3-compatible services while the AI provider remains fake.

On the frontend, tests cover:

  • UI primitives,
  • auth API functions,
  • auth session storage,
  • login form validation,
  • auth provider behavior,
  • auth gate behavior,
  • app shell components,
  • home components,
  • topic carousel behavior,
  • login flow integration at component/provider level.

E2E testing is intentionally postponed until the main flows stabilize. Maestro is a likely candidate later for login, topic selection, image capture, analysis and collection flows.

Local Development

The local environment is designed to support realistic backend development without requiring real production services.

The development stack includes:

  • PostgreSQL.
  • OpenAPI documentation.
  • A browser API client for the generated contract.
  • A local tools hub.
  • Optional S3-compatible storage configuration.
  • Fake AI by default.

OpenAPI generation is integrated into the workflow, and the local API client can consume that contract. This mirrors the same philosophy used in other projects: the API contract should be easy to inspect, regenerate and exercise during development.

Privacy and Public Presentation

Collectum is private, and that is intentional. The project contains product strategy, implementation decisions and architecture that I do not want to expose as an open repository at this stage.

For that reason, this article avoids:

  • repository links,
  • private endpoint catalogs,
  • secret names beyond generic configuration concepts,
  • provider credentials,
  • detailed prompt contents,
  • business-sensitive implementation code,
  • deployment-specific infrastructure details.

What is safe to show is the engineering shape: the product loop, backend domains, asynchronous analysis workflow, credit accounting, testing strategy, mobile architecture and design direction.

What Collectum Demonstrates

Collectum demonstrates work across the full product stack:

  • Mobile UI and UX design with React Native and Expo.
  • Backend API design in Go.
  • PostgreSQL persistence and migrations.
  • AI provider isolation.
  • Asynchronous worker processing.
  • S3-compatible image storage.
  • Credit accounting before expensive operations.
  • Auth sessions and secure mobile token persistence.
  • OpenAPI-driven development tooling.
  • Unit, component and integration testing.
  • Monorepo automation with pnpm, Turbo, Task and Husky.

It is a private project, but it is not a small prototype. It is a product-sized system with real domain boundaries, operational concerns and a growing test suite.

Conclusion

Collectum is a mobile-first AI collection app built with a careful full-stack architecture. The product idea is simple and approachable, but the implementation touches complex areas: image handling, AI analysis, asynchronous workers, cost control, auth, storage, mobile UX, contracts and tests.

The project is valuable precisely because it forces product design and engineering constraints to meet. It is playful on the surface, but underneath it is a serious exercise in building a scalable, testable and economically aware AI application.