shipany-ai-generator
v0.1.29
Published
Shared AI image/video generator configuration and runtime core.
Readme
shipany-ai-generator
Shared AI image/video generator runtime and ShipAny-style React UI.
This package is designed for ShipAny/Next/Tailwind template variants. Keep the component code in one package, and let each project provide its own model configuration, API adapter, login, credits, paywall, and copy.
Recommended Workflow
Use one project as the baseline dogfood project.
- Develop and test the generator in the baseline project with real auth, credits, uploads, paywall, Tailwind theme, and API routes.
- Build and publish a new package version.
- Upgrade other template projects to the new npm package version.
Do not copy generator source files between projects once the package is in use. Other projects should keep only their own config and adapter wiring.
Install
pnpm add shipany-ai-generatorRequired peer dependencies are expected to already exist in ShipAny template projects:
pnpm add react framer-motion lucide-reactIf the consuming project uses Tailwind CSS v4, scan the package output so the ShipAny skin classes are generated:
@import 'tailwindcss';
@source '../../node_modules/shipany-ai-generator/dist';Adjust the relative path to match the app's CSS file location.
ShipAny UI Usage
'use client';
import { createFetchGeneratorAdapter } from 'shipany-ai-generator/adapters';
import { ShipAnyGenerator } from 'shipany-ai-generator/shipany';
const adapter = createFetchGeneratorAdapter({
generateUrl: '/api/ai/generate',
queryUrl: '/api/ai/query',
cancelUrl: '/api/ai/cancel',
uploadUrl: '/api/storage/upload-image',
downloadUrl: '/api/proxy/file',
transformRequest(request) {
const options = { ...request.options };
if (request.inputImages.length > 0) {
options.image_input = request.inputImages;
}
return {
mediaType: request.outputType,
scene: request.scene,
provider: request.provider,
model: request.model,
prompt: request.prompt,
options,
};
},
});
export function Generator({ user, isPaid, credits }) {
return (
<ShipAnyGenerator
config={videoConfig}
adapter={adapter}
app={{
user,
isPaid,
isPaidReady: true,
credits: {
remaining: credits?.remainingCredits ?? 0,
unlimited: credits?.isUnlimited,
},
requestSignIn: () => openSignInDialog(),
openPaywall: () => openPaymentDialog(),
notify: {
success: (message) => toast.success(message),
error: (message) => toast.error(message),
info: (message) => toast.message(message),
},
track: (event, payload) => track(event, payload),
}}
estimateCredits={(request) => estimateProjectCredits(request)}
onResult={() => refreshCredits()}
/>
);
}estimateCredits is optional. If omitted, the package uses its legacy generic
estimate. Projects that configure their own models or credit rules should pass
their own estimator and use the same function on the server when charging
credits.
Config Examples
Video Generator
import { createKieVideoGeneratorConfig } from 'shipany-ai-generator';
export const videoConfig = createKieVideoGeneratorConfig({
demoVideos: ['/videos/demo-1.mp4', '/videos/demo-2.mp4'],
});createKieVideoGeneratorConfig() includes the default Kie video model presets:
- Kling 3.0 (
kling-3.0) maps requests tokling-3.0/video, supportsstd/pro/4K,16:9/9:16/1:1, durations from 3 to 15 seconds, one start-frame image, or two first/last-frame images. - Veo 3.1 (
veo3) maps modes toveo3_lite,veo3_fast, andveo3, supports16:9/9:16/auto, text, first/last-frame, and reference generation types. Reference mode is normalized tofastand allows up to 3 input images.1080pand4kare marked as paid options by default. - Seedance 2.0 (
seedance-2) maps requests tobytedance/seedance-2, supports480p/720p/1080p,16:9/4:3/1:1/3:4/9:16/21:9, up to 9 reference images, and two first/last-frame images.generate_audiodefaults tofalse.
The default list intentionally does not include Seedance 2.0 Fast unless a project wires that provider path itself.
Projects can crop or lock video options the same way as image options:
import {
createKieVideoGeneratorConfig,
KIE_VIDEO_MODEL_PRESETS,
} from 'shipany-ai-generator';
const kling = KIE_VIDEO_MODEL_PRESETS.find(
(model) => model.id === 'kling-3.0'
)!;
export const videoConfig = createKieVideoGeneratorConfig({
models: [
{
...kling,
modeOptions: [
{ value: 'std', label: 'Standard' },
{
value: '4K',
label: '4K',
requiresPaid: true,
paywallFeature: 'video_4k',
},
],
},
],
});Image Generator
import { createKieImageGeneratorConfig } from 'shipany-ai-generator';
export const imageConfig = createKieImageGeneratorConfig({
defaultPrompt: 'Draw this in rough MS Paint style.',
defaultModel: 'gpt-image-2',
promptPlaceholder: 'Upload an image, then describe the redraw.',
defaultOutputCount: 1,
outputCountOptions: [
{ value: 1, label: '1 image' },
{ value: 2, label: '2 images' },
{ value: 4, label: '4 images' },
],
demoImages: ['/imgs/demo.webp'],
});createKieImageGeneratorConfig() includes the default Kie image model presets:
- GPT Image 2 (
gpt-image-2) maps requests togpt-image-2-text-to-imageorgpt-image-2-image-to-image, defaults to1K + auto, supports 16 input images, and changes aspect ratio options by resolution. - Nano Banana 2 (
nano-banana-2) defaults to2K + auto + jpg, supports 14 input images,1K/2K/4K,jpg/png, and the full Kie aspect ratio set.
GPT Image 2 aspect ratio options depend on resolution:
| Resolution | Aspect ratios |
| ---------- | ------------------------------------------- |
| 1K | auto, 1:1, 9:16, 16:9, 4:3, 3:4 |
| 2K | 1:1, 9:16, 16:9, 4:3, 3:4 |
| 4K | 9:16, 16:9, 4:3, 3:4 |
The UI hides invalid combinations, and buildGeneratorRequest() normalizes
stale local-storage or URL state before sending a request. For example,
gpt-image-2 + 4K + 1:1 is converted to a valid preset default instead of
being submitted to Kie.
Projects can crop or lock preset options by passing their own models array or
option objects. Use requiresPaid and paywallFeature on any option that
should open the paywall:
import {
createKieImageGeneratorConfig,
KIE_IMAGE_MODEL_PRESETS,
} from 'shipany-ai-generator';
const gptImage2 = KIE_IMAGE_MODEL_PRESETS.find(
(model) => model.id === 'gpt-image-2'
)!;
export const imageConfig = createKieImageGeneratorConfig({
models: [
{
...gptImage2,
defaultResolution: '2K',
resolutionOptions: [
{ value: '2K', label: '2K' },
{
value: '4K',
label: '4K',
requiresPaid: true,
paywallFeature: 'image_4k',
},
],
},
],
});Output Count
The package supports configurable image output count. This is different from
maxImages:
maxImagescontrols how many input/reference images the user may upload.defaultOutputCountcontrols how many generated images are requested by default.outputCountOptionscontrols which output counts appear in Settings.
Example:
{
"outputType": "image",
"defaultOutputCount": 1,
"outputCountOptions": [
{ "value": 1, "label": "1 image" },
{ "value": 2, "label": "2 images" },
{ "value": 4, "label": "4 images" }
]
}The selected value is saved in local storage with the rest of the generator settings. When the user submits, the package sends both:
request.options.output_count; // generic package field
request.options.image_count; // image-specific backend fieldCurrent backend support:
- Go Worker Kie image generation supports
image_countfrom 1 to 4. - Go Worker clamps invalid values to the 1-4 range.
- Go Worker generates each image as a separate Kie task and returns all image URLs together.
- Video generation currently remains single-output by default. Do not expose
outputCountOptionsfor video models unless the backend/provider explicitly supports multi-video generation and the billing model is updated.
Billing must multiply image cost by the selected output count. In this template,
/api/ai/generate reads options.image_count or options.output_count and
multiplies image credits by that value.
For project wrappers, only expose output count when the configured provider
supports it. In the current ShipAny wrapper, output count is shown for the
go-worker provider and hidden for direct kie provider to avoid displaying a
control that the provider path does not honor.
URL Contract
The package reads these query params automatically:
- Prompt:
prompt,prompts; multiple values or comma-separated values use the last one. - Preview images:
previewImage,previewImages,previewImg,previewImgs. - Preview videos:
previewVideo,previewVideos. - Input images:
inputImage,inputImages,referenceImage,referenceImages. - Bare media keys are preview-only:
image,img,images,video,videos.
Input images affect scene inference. Bare media keys do not.
Runtime Behavior
- Scene is inferred from
outputTypeand uploaded/input images. text-to-video/image-to-videoandtext-to-image/image-to-imageare handled by one input box.- If the user clicks generate while signed out,
requestSignInis called and generation resumes after login if the prompt is unchanged. - Uploaded images are limited by model-level
maxImagesfirst, then config-levelmaxImages, plusmaxSizeMB. - Multiple demo media and multiple result URLs are shown with thumbnail switching.
- Download uses
adapter.downloadwhen provided;createFetchGeneratorAdapter({ downloadUrl })downloads through a proxy endpoint.
Adapter Contract
type GeneratorAdapter = {
generate(request: GeneratorRequest): Promise<unknown>;
query?(taskId: string): Promise<unknown>;
cancel?(taskId: string): Promise<void>;
download?(url: string): Promise<Blob>;
uploadImages?(files: File[]): Promise<string[]>;
};createFetchGeneratorAdapter expects JSON responses shaped either as raw data
or { code, message, data }. Upload responses may return URL strings or objects
with url, src, imageUrl, or uri.
Exports
import {
buildGeneratorRequest,
type GeneratorConfig,
} from 'shipany-ai-generator';
import { createFetchGeneratorAdapter } from 'shipany-ai-generator/adapters';
import { AiGenerator } from 'shipany-ai-generator/react';
import { ShipAnyGenerator } from 'shipany-ai-generator/shipany';Publishing a New Version
From the baseline project:
pnpm --filter shipany-ai-generator build
pnpm -C packages/ai-generator pack --pack-destination /tmpThen bump packages/ai-generator/package.json:
{
"name": "shipany-ai-generator",
"version": "0.1.x"
}Publish:
pnpm -C packages/ai-generator publish --access public --registry=https://registry.npmjs.org/After publishing, upgrade consumers:
pnpm add [email protected]