This repository contains ArtCraft's backend, HTTP API, background workers, and web frontends. It is a Rust and TypeScript monorepo with shared API definitions, provider clients, database queries, and development tooling.
The Tauri desktop application is maintained in storytold/artcraft, along with the product overview, feature demos, and desktop downloads.
storyteller-web is the main HTTP service,
built with Rust, Actix Web, and Tokio. It handles authentication, accounts,
media uploads and libraries, generation requests, job status, credits, and Stripe
billing. The service retains the storyteller-web name, and its hosted API uses
https://api.storyteller.ai.
Generation spans the HTTP service, provider integrations, and asynchronous workers:
flowchart LR
Clients[Web, desktop, and API clients] --> API[storyteller-web]
API --> Router[artcraft_router]
Router --> Providers[Generation providers]
Providers -->|Webhooks| API
Workers[Background workers] -->|Poll jobs| Providers
API --> DB[(MySQL)]
Workers --> DB
API --> Storage[(Object storage)]
Workers --> Storage
A typical generation request follows this path:
artcraft_router to build and
submit a provider-specific request. The API records inference jobs in MySQL
and returns job tokens to the client.Storage responsibilities are split across these components:
| Component | Role |
|---|---|
| MySQL + SQLx | Accounts, media metadata, inference jobs, wallets, and bills |
| Redis | Caching, rate limiting, and job progress |
| Elasticsearch | Search indexes and queries |
| S3-compatible storage / R2 | Uploaded media, generated assets, and derived files |
HTTP routes and handlers live in
storyteller_web/src/http_server.
MySQL queries belong in the shared
mysql_queries crate so that handlers,
workers, and CLI tools use the same data access layer. Reusable billing components
live under crates/service/plugins, and background
services live under crates/service/job.
The API exposes two generation interfaces:
/v1/omni_gen/generate/* uses user sessions for image,
video, audio, mesh, and splat generation. /v1/omni_gen/models/* and
/v1/omni_gen/cost/* expose model discovery and cost estimation without requiring
a user session. Application job status is available under /v1/jobs./v1/omni_api uses an API key in the Authorization
header. It provides image and video generation, image/video/audio uploads, and
job-status polling. Use Authorization: Bearer <api-key>; API access must be
enabled for the account.For example, a programmatic video request goes to
POST /v1/omni_api/generate/video. The response contains an
inference_job_token, which the caller polls with
GET /v1/omni_api/job_status/job/{token}. The
Omni API guide covers authentication,
request and response bodies, URL inputs, and runnable examples.
Start with these sources when adding or tracing an endpoint:
frontend contains the Nx workspace for React and TypeScript apps
and shared libraries. The main web frontends use Vite, with Zustand
and signals for state, Three.js for 3D scenes, and shared UI and generation tools.
| Path | Purpose |
|---|---|
frontend/apps/artcraft-webapp | Browser application at app.getartcraft.com |
frontend/apps/artcraft-website | Product website at getartcraft.com |
frontend/libs/api | HTTP clients, API host selection, and models |
frontend/libs/omni-gen | Shared generation logic |
frontend/libs/components | Reusable UI, editors, and generation controls |
frontend/libs/tauri-api | Frontend bindings for native desktop commands |
The web apps call the backend through the shared API library, which handles JSON
and multipart requests and session credentials. Libraries such as tauri-api and
tauri-utils remain because shared web components still import their types,
helpers, and browser-compatible behavior. The native desktop app and libraries
used only by that app live in the separate desktop repository.
artcraft-services/
├── crates/
│ ├── service/web/ # HTTP services, including storyteller_web
│ ├── service/job/ # Provider workers, media processing, analytics
│ ├── service/plugins/ # Shared billing and service components
│ ├── api_clients/ # ArtCraft API types, clients, router, provider clients
│ ├── schema/ # Database access, public tokens/enums, bucket paths
│ ├── lib/ # Shared Rust utilities
│ └── cli/ # Development and operations tools
├── frontend/
│ ├── apps/ # Web frontends
│ └── libs/ # Shared TypeScript libraries
├── _database/ # SQL migrations, materialized schemas, search schemas
├── _docs/ # Setup guides and technical documentation
├── _tools/postman/ # HTTP request collections
├── build/ # Service Dockerfiles
├── script/ # Development, build, and database tooling
└── Cargo.toml # Rust workspace
Use Rust/Cargo for backend work and Node.js/npm for the main frontend workspace. See the development setup guide for toolchain setup and frontend README for dependency installation and Nx usage.
The server needs a migrated MySQL database, Redis, Elasticsearch configuration, object storage, and credentials for the integrations being exercised. The server setup guide covers local MySQL and Redis; the remaining configuration is defined in the server config directory and startup code.
In development, the server loads storyteller-web.common.env,
storyteller-web.development.env, and storyteller-web.development-secrets.env
from its configuration search paths: the repository root, ./config, and the
server's config directory. Its bootstrap skips the root .env file.
With the toolchain and service configuration in place, run from the repository root:
SQLX_OFFLINE=true cargo check -p storyteller-web
SQLX_OFFLINE=true cargo run -p storyteller-web
The default bind address is 0.0.0.0:12345, configurable through BIND_ADDRESS.
GET /_status exposes the service health check. Provider polling and thumbnail
processing require their corresponding worker processes and configuration.
SQLX_OFFLINE=true uses the checked-in .sqlx query metadata during compilation;
the running server still needs its databases. When changing SQLx queries, use
script/rust/sqlx_codegen_database.sh
to regenerate metadata against migrated development databases.
To run the browser app against a local backend:
cd frontend
npm install
VITE_USE_LOCAL_API=true npx nx dev artcraft-webapp
The browser app runs at http://localhost:4201. VITE_USE_LOCAL_API=true selects
http://localhost:12345; without that override, its Vite development proxy targets
the hosted API. API host selection lives in
StorytellerApiHostStore.
From frontend, build the web app or run the product website with:
npx nx build artcraft-webapp
npx nx dev artcraft-website
The website runs at http://localhost:4200. Repository-root launchers are in
script/website. For desktop development, use the
ArtCraft desktop repository.
Rust
64.0%
TypeScript
34.7%
This repository contains ArtCraft's backend, HTTP API, background workers, and web frontends. It is a Rust and TypeScript monorepo with shared API definitions, provider clients, database queries, and development tooling.
The Tauri desktop application is maintained in storytold/artcraft, along with the product overview, feature demos, and desktop downloads.
storyteller-web is the main HTTP service,
built with Rust, Actix Web, and Tokio. It handles authentication, accounts,
media uploads and libraries, generation requests, job status, credits, and Stripe
billing. The service retains the storyteller-web name, and its hosted API uses
https://api.storyteller.ai.
Generation spans the HTTP service, provider integrations, and asynchronous workers:
flowchart LR
Clients[Web, desktop, and API clients] --> API[storyteller-web]
API --> Router[artcraft_router]
Router --> Providers[Generation providers]
Providers -->|Webhooks| API
Workers[Background workers] -->|Poll jobs| Providers
API --> DB[(MySQL)]
Workers --> DB
API --> Storage[(Object storage)]
Workers --> Storage
A typical generation request follows this path:
artcraft_router to build and
submit a provider-specific request. The API records inference jobs in MySQL
and returns job tokens to the client.Storage responsibilities are split across these components:
| Component | Role |
|---|---|
| MySQL + SQLx | Accounts, media metadata, inference jobs, wallets, and bills |
| Redis | Caching, rate limiting, and job progress |
| Elasticsearch | Search indexes and queries |
| S3-compatible storage / R2 | Uploaded media, generated assets, and derived files |
HTTP routes and handlers live in
storyteller_web/src/http_server.
MySQL queries belong in the shared
mysql_queries crate so that handlers,
workers, and CLI tools use the same data access layer. Reusable billing components
live under crates/service/plugins, and background
services live under crates/service/job.
The API exposes two generation interfaces:
/v1/omni_gen/generate/* uses user sessions for image,
video, audio, mesh, and splat generation. /v1/omni_gen/models/* and
/v1/omni_gen/cost/* expose model discovery and cost estimation without requiring
a user session. Application job status is available under /v1/jobs./v1/omni_api uses an API key in the Authorization
header. It provides image and video generation, image/video/audio uploads, and
job-status polling. Use Authorization: Bearer <api-key>; API access must be
enabled for the account.For example, a programmatic video request goes to
POST /v1/omni_api/generate/video. The response contains an
inference_job_token, which the caller polls with
GET /v1/omni_api/job_status/job/{token}. The
Omni API guide covers authentication,
request and response bodies, URL inputs, and runnable examples.
Start with these sources when adding or tracing an endpoint:
frontend contains the Nx workspace for React and TypeScript apps
and shared libraries. The main web frontends use Vite, with Zustand
and signals for state, Three.js for 3D scenes, and shared UI and generation tools.
| Path | Purpose |
|---|---|
frontend/apps/artcraft-webapp | Browser application at app.getartcraft.com |
frontend/apps/artcraft-website | Product website at getartcraft.com |
frontend/libs/api | HTTP clients, API host selection, and models |
frontend/libs/omni-gen | Shared generation logic |
frontend/libs/components | Reusable UI, editors, and generation controls |
frontend/libs/tauri-api | Frontend bindings for native desktop commands |
The web apps call the backend through the shared API library, which handles JSON
and multipart requests and session credentials. Libraries such as tauri-api and
tauri-utils remain because shared web components still import their types,
helpers, and browser-compatible behavior. The native desktop app and libraries
used only by that app live in the separate desktop repository.
artcraft-services/
├── crates/
│ ├── service/web/ # HTTP services, including storyteller_web
│ ├── service/job/ # Provider workers, media processing, analytics
│ ├── service/plugins/ # Shared billing and service components
│ ├── api_clients/ # ArtCraft API types, clients, router, provider clients
│ ├── schema/ # Database access, public tokens/enums, bucket paths
│ ├── lib/ # Shared Rust utilities
│ └── cli/ # Development and operations tools
├── frontend/
│ ├── apps/ # Web frontends
│ └── libs/ # Shared TypeScript libraries
├── _database/ # SQL migrations, materialized schemas, search schemas
├── _docs/ # Setup guides and technical documentation
├── _tools/postman/ # HTTP request collections
├── build/ # Service Dockerfiles
├── script/ # Development, build, and database tooling
└── Cargo.toml # Rust workspace
Use Rust/Cargo for backend work and Node.js/npm for the main frontend workspace. See the development setup guide for toolchain setup and frontend README for dependency installation and Nx usage.
The server needs a migrated MySQL database, Redis, Elasticsearch configuration, object storage, and credentials for the integrations being exercised. The server setup guide covers local MySQL and Redis; the remaining configuration is defined in the server config directory and startup code.
In development, the server loads storyteller-web.common.env,
storyteller-web.development.env, and storyteller-web.development-secrets.env
from its configuration search paths: the repository root, ./config, and the
server's config directory. Its bootstrap skips the root .env file.
With the toolchain and service configuration in place, run from the repository root:
SQLX_OFFLINE=true cargo check -p storyteller-web
SQLX_OFFLINE=true cargo run -p storyteller-web
The default bind address is 0.0.0.0:12345, configurable through BIND_ADDRESS.
GET /_status exposes the service health check. Provider polling and thumbnail
processing require their corresponding worker processes and configuration.
SQLX_OFFLINE=true uses the checked-in .sqlx query metadata during compilation;
the running server still needs its databases. When changing SQLx queries, use
script/rust/sqlx_codegen_database.sh
to regenerate metadata against migrated development databases.
To run the browser app against a local backend:
cd frontend
npm install
VITE_USE_LOCAL_API=true npx nx dev artcraft-webapp
The browser app runs at http://localhost:4201. VITE_USE_LOCAL_API=true selects
http://localhost:12345; without that override, its Vite development proxy targets
the hosted API. API host selection lives in
StorytellerApiHostStore.
From frontend, build the web app or run the product website with:
npx nx build artcraft-webapp
npx nx dev artcraft-website
The website runs at http://localhost:4200. Repository-root launchers are in
script/website. For desktop development, use the
ArtCraft desktop repository.
Rust
64.0%
TypeScript
34.7%