{
const now = new Date().toISOString();
const supabase = getSupabaseClient();
const { data, error } = await supabase
.from("orders")
.select("*")
.eq("user_uuid", user_uuid)
.eq("status", "paid")
.order("created_at", { ascending: false });
if (error) {
return undefined;
}
return data;
}
```
--------------------------------
### 生成数据库迁移文件
Source: https://docs.shipany.ai/zh/features/database
在完成 Schema 和配置修改后,执行此命令以生成数据库迁移文件。
```bash
pnpm db:generate
```
--------------------------------
### Get User UUID and Redirect if Not Logged In
Source: https://docs.shipany.ai/zh/user-console/new-table
Fetches the current user's UUID from the session. If the user is not logged in, it redirects them to the sign-in page.
```typescript
import { getUserUuid } from "@/services/user";
import { redirect } from "next/navigation";
export default async function MyOrdersPage() {
const user_uuid = await getUserUuid();
const callbackUrl = `${process.env.NEXT_PUBLIC_WEB_URL}/my-orders`;
if (!user_uuid) {
redirect(`/auth/signin?callbackUrl=${encodeURIComponent(callbackUrl)}`);
}
return My Orders With User UUID: {user_uuid}
;
}
```
--------------------------------
### 数据库迁移命令
Source: https://docs.shipany.ai/zh/features/database
用于初始化或增量更新数据库表的迁移命令。
```bash
pnpm db:migrate
```
--------------------------------
### 配置 OpenRouter API 环境变量
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
在 .env 文件中设置 OpenRouter 的 API Key。
```env
OPENROUTER_API_KEY = "sk-or-v1-xxx";
```
--------------------------------
### 配置谷歌一键登录环境变量
Source: https://docs.shipany.ai/zh/features/oauth
在 .env.development 文件中配置谷歌一键登录所需的 ID 和启用标志。NEXT_PUBLIC_AUTH_GOOGLE_ONE_TAP_ENABLED 设置为 "true" 以启用。
```dotenv
NEXT_PUBLIC_AUTH_GOOGLE_ONE_TAP_ENABLED = "true"
NEXT_PUBLIC_AUTH_GOOGLE_ID = "4680xx-xxx.apps.googleusercontent.com"
```
--------------------------------
### Generate Metadata for New Routes
Source: https://docs.shipany.ai/zh/features/seo
Configure metadata for new page routes (page.tsx) to set independent title, description, and canonical information for improved SEO. This example shows how to dynamically generate canonical URLs based on locale.
```typescript
import { getTranslations } from "next-intl/server";
export async function generateMetadata({
params: { locale },
}: {
params: { locale: string };
}) {
const t = await getTranslations();
let canonicalUrl = `${process.env.NEXT_PUBLIC_WEB_URL}/posts`;
if (locale !== "en") {
canonicalUrl = `${process.env.NEXT_PUBLIC_WEB_URL}/${locale}/posts`;
}
return {
title: t("blog.title"),
description: t("blog.description"),
alternates: {
canonical: canonicalUrl,
},
};
}
```
--------------------------------
### 检查 Node.js 版本
Source: https://docs.shipany.ai/zh/guide/good-to-know
验证当前安装的 Node.js 和 npm 版本是否符合开发要求。
```bash
$ node -v
v22.2.0
$ npm -v
10.7.0
```
--------------------------------
### Default Theme Configuration
Source: https://docs.shipany.ai/zh
Set the default theme for the application.
```env
NEXT_PUBLIC_DEFAULT_THEME = "light"
```
--------------------------------
### 配置谷歌登录环境变量
Source: https://docs.shipany.ai/zh/features/oauth
在 .env.development 文件中配置谷歌登录所需的 ID、Secret 和启用标志。NEXT_PUBLIC_AUTH_GOOGLE_ENABLED 设置为 "true" 以启用谷歌登录。
```dotenv
AUTH_GOOGLE_ID = "4680xx-xxx.apps.googleusercontent.com"
AUTH_GOOGLE_SECRET = "GOxxx"
NEXT_PUBLIC_AUTH_GOOGLE_ENABLED = "true"
```
--------------------------------
### 克隆 Cloudflare 分支
Source: https://docs.shipany.ai/zh/deploy/deploy-to-cloudflare
使用 git 命令拉取预配置好的 cloudflare 分支以支持一键部署。
```bash
git clone -b cloudflare git@github.com:shipanyai/shipany-template-one.git my-shipany-project
```
--------------------------------
### 创建 Wrangler 配置文件
Source: https://docs.shipany.ai/zh/deploy/deploy-to-cloudflare
从示例文件复制并创建 Cloudflare Workers 所需的 wrangler.toml 配置文件。
```bash
cp wrangler.toml.example wrangler.toml
```
--------------------------------
### 启动数据库管理界面
Source: https://docs.shipany.ai/zh/features/database
启动 Drizzle Studio 以查看和管理数据库表。
```bash
pnpm db:studio
```
--------------------------------
### View Blog List
Source: https://docs.shipany.ai/zh/features/blog
URL format to view the list of all blog posts. Replace {your-domain} and {locale} with the appropriate values.
```url
https://{your-domain}/{locale}/posts
```
--------------------------------
### 配置 Github 登录环境变量
Source: https://docs.shipany.ai/zh/features/oauth
在 .env.development 文件中配置 Github 登录所需的 ID、Secret 和启用标志。NEXT_PUBLIC_AUTH_GITHUB_ENABLED 设置为 "true" 以启用 Github 登录。
```dotenv
AUTH_GITHUB_ID = "xxx"
AUTH_GITHUB_SECRET = "xxx"
NEXT_PUBLIC_AUTH_GITHUB_ENABLED = "true"
```
--------------------------------
### Build Project Locally
Source: https://docs.shipany.ai/zh/guide/faq
Execute this command to build the project locally after resolving merge conflicts, ensuring the project runs correctly and has no compilation errors.
```bash
pnpm build
```
--------------------------------
### 配置云存储环境变量
Source: https://docs.shipany.ai/zh/features/storage
在 .env 文件中设置 AWS S3 兼容存储的连接参数。
```text
STORAGE_ENDPOINT = ""
STORAGE_REGION = ""
STORAGE_ACCESS_KEY = ""
STORAGE_SECRET_KEY = ""
STORAGE_BUCKET = ""
STORAGE_DOMAIN = ""
```
--------------------------------
### Implement User Center Console Layout
Source: https://docs.shipany.ai/zh/user-console/console
This code demonstrates how to implement a user center layout using the provided ConsoleLayout component. It fetches user information, redirects to sign-in if the user is not authenticated, and configures the sidebar navigation with user-specific links.
```typescript
import ConsoleLayout from "@/components/console/layout";
import { ReactNode } from "react";
import { Sidebar } from "@/types/blocks/sidebar";
import { getTranslations } from "next-intl/server";
import { getUserInfo } from "@/services/user";
import { redirect } from "next/navigation";
export default async function ({ children }: { children: ReactNode }) {
const userInfo = await getUserInfo();
if (!userInfo || !userInfo.email) {
redirect("/auth/signin");
}
const t = await getTranslations();
const sidebar: Sidebar = {
nav: {
items: [
{
title: t("user.my_orders"),
url: "/my-orders",
icon: "RiOrderPlayLine",
is_active: true,
},
],
},
};
return {children};
}
```
--------------------------------
### 配置 Kling AI 环境变量
Source: https://docs.shipany.ai/zh/ai-integrations/video-generation
在 .env.development 文件中设置 Kling AI 的访问密钥和密钥。
```text
KLING_ACCESS_KEY = "xxx"
KLING_SECRET_KEY = "xxx"
```
--------------------------------
### Create Blog Posts Table
Source: https://docs.shipany.ai/zh/features/blog
SQL statement to create the 'posts' table in the database for storing blog content. Ensure database configuration is completed before running.
```sql
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
uuid VARCHAR(255) UNIQUE NOT NULL,
slug VARCHAR(255),
title VARCHAR(255),
description TEXT,
content TEXT,
created_at timestamptz,
updated_at timestamptz,
status VARCHAR(50),
cover_url VARCHAR(255),
author_name VARCHAR(255),
author_avatar_url VARCHAR(255),
locale VARCHAR(50)
);
```
--------------------------------
### 配置 OpenAI 兼容模型环境变量
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
为兼容 OpenAI API 的第三方服务(如智谱 AI)设置基础 URL 和 API Key。
```env
ZHIPU_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
ZHIPU_API_KEY = "xxx";
```
--------------------------------
### 调用 Kling AI 生成视频
Source: https://docs.shipany.ai/zh/ai-integrations/video-generation
使用 ShipAny 自定义的 generateVideo 方法和 kling provider 进行视频生成。注意该方法默认同步执行,需等待生成完成。
```typescript
import { generateVideo } from "@/aisdk";
import { kling } from "@/aisdk/kling";
const prompt = "a beautiful girl running with 2 cats";
const model = "kling-v1-6";
const videoModel = kling.video(model);
const providerOptions = {
kling: {
mode: "std",
duration: 5,
},
};
const { videos, warnings } = await generateVideo({
model: videoModel,
prompt: prompt,
n: 1,
providerOptions,
});
```
--------------------------------
### Clone ShipAny Project Repository
Source: https://docs.shipany.ai/zh
Use this command to clone the ShipAny project template to your local machine for development.
```bash
git clone git@github.com:shipanyai/shipany-template-one.git my-shipany-project
```
--------------------------------
### 检查 Git 版本
Source: https://docs.shipany.ai/zh/guide/good-to-know
确认系统中已安装 Git 及其版本信息。
```bash
$ git --version
git version 2.39.3 (Apple Git-146)
```
--------------------------------
### 配置环境变量
Source: https://docs.shipany.ai/zh/features/database
在 .env 文件中设置 DATABASE_URL 以连接数据库。
```text
DATABASE_URL="postgresql://postgres.defqvdpquwyqqjlmurkg:******@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres"
```
--------------------------------
### 下载并上传远程图片
Source: https://docs.shipany.ai/zh/features/storage
直接通过远程 URL 下载图片并上传至云存储。
```typescript
import { newStorage } from "@/lib/storage";
const storage = newStorage();
const res = await storage.downloadAndUpload({
url: "https://shipany.ai/logo.png",
key: `shipany/logo.png`,
});
```
--------------------------------
### Configure Creem Payment Environment Variables
Source: https://docs.shipany.ai/zh/features/payment/creem
Set these environment variables in your ShipAny project configuration files (`.env.development`, `.env.production`, or `wrangler.toml`) to enable Creem payments. Ensure `PAY_PROVIDER` is set to `creem` and provide the correct API key, webhook secret, and product mappings for your Creem environment.
```env
NEXT_PUBLIC_WEB_URL = "http://localhost:3000"
NEXT_PUBLIC_PAY_SUCCESS_URL = "/my-orders"
NEXT_PUBLIC_PAY_FAIL_URL = "/pricing"
NEXT_PUBLIC_PAY_CANCEL_URL = "/pricing"
PAY_PROVIDER = "creem"
CREEM_ENV = "test"
CREEM_API_KEY = "creem_test_xxx"
CREEM_WEBHOOK_SECRET = "whsec_xxx"
CREEM_PRODUCTS = '{"starter": "prod_xxx", "standard": "prod_xxx", "premium": "prod_xxx"}'
```
--------------------------------
### 使用 OpenAI 兼容模型生成文本
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
利用 @ai-sdk/openai-compatible 调用兼容 OpenAI 接口的第三方模型。
```typescript
import { generateText } from "ai";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
const zhipu = createOpenAICompatible({
name: "zhipu",
apiKey: process.env.ZHIPU_API_KEY,
baseURL: process.env.ZHIPU_BASE_URL,
});
const prompt = "who are you?";
const model = "glm-4-flash";
const textModel = zhipu(model);
const { text, warnings } = await generateText({
model: textModel,
prompt: prompt,
});
if (warnings && warnings.length > 0) {
throw new Error("gen text failed");
}
console.log("gen text ok:", text);
```
--------------------------------
### 配置 OpenAI 环境变量
Source: https://docs.shipany.ai/zh/ai-integrations/image-generation
设置 OpenAI API 的基础 URL 和密钥。
```text
OPENAI_BASE_URL = "https://api.openai.com/v1"
OPENAI_API_KEY = "sk-xxx"
```
--------------------------------
### 实现管理后台布局
Source: https://docs.shipany.ai/zh/admin-system/layout
在 Next.js 布局文件中引入 DashboardLayout,并根据用户权限配置侧边栏导航结构。
```typescript
import DashboardLayout from "@/components/dashboard/layout";
import { ReactNode } from "react";
import { Sidebar } from "@/types/blocks/sidebar";
import { getUserInfo } from "@/services/user";
import { redirect } from "next/navigation";
export default async function AdminLayout({
children,
}: {
children: ReactNode;
}) {
const userInfo = await getUserInfo();
if (!userInfo || !userInfo.email) {
redirect("/auth/signin");
}
const adminEmails = process.env.ADMIN_EMAILS?.split(",");
if (!adminEmails?.includes(userInfo?.email)) {
return (
No access
);
}
const sidebar: Sidebar = {
brand: {
title: "ShipAny",
logo: {
src: "/logo.png",
alt: "ShipAny",
},
},
nav: {
items: [
{
title: "Users",
url: "/admin/users",
icon: "RiUserLine",
},
{
title: "Orders",
icon: "RiOrderPlayLine",
is_expand: true,
children: [
{
title: "Paid Orders",
url: "/admin/paid-orders",
},
],
},
],
},
social: {
items: [
{
title: "Home",
url: "/",
target: "_blank",
icon: "RiHomeLine",
},
{
title: "Github",
url: "https://github.com/shipanyai/shipany-template-one",
target: "_blank",
icon: "RiGithubLine",
},
{
title: "Discord",
url: "https://discord.gg/HQNnrzjZQS",
target: "_blank",
icon: "RiDiscordLine",
},
{
title: "X",
url: "https://x.com/shipanyai",
target: "_blank",
icon: "RiTwitterLine",
},
],
},
};
return {children};
}
```
--------------------------------
### 安装 React Email 依赖
Source: https://docs.shipany.ai/zh/features/email/resend
使用 pnpm 安装必要的 React Email 组件库。
```bash
pnpm add resend @react-email/components
```
--------------------------------
### 上传本地文件到云存储
Source: https://docs.shipany.ai/zh/features/storage
读取本地文件系统中的文件并上传。注意此方法在 Edge Runtime 环境下不可用。
```typescript
import path from "path";
import { readFile } from "fs/promises";
import { newStorage } from "@/lib/storage";
const storage = newStorage();
const content = await readFile(path.join(process.cwd(), "sing.m4a"));
const res = await storage.uploadFile({
body: content,
key: `shipany/sing_${getUuid()}.mp3`,
contentType: "audio/mpeg",
});
```
--------------------------------
### Configure Robots.txt
Source: https://docs.shipany.ai/zh/features/seo
Adjust the `public/robots.txt` file to control search engine crawling. Disallow specific paths to prevent indexing.
```text
User-agent: *
Disallow: /*?*q=
Disallow: /privacy-policy
Disallow: /terms-of-service
```
--------------------------------
### 执行部署命令
Source: https://docs.shipany.ai/zh/deploy/deploy-to-cloudflare
在项目根目录运行部署脚本以启动发布流程。
```bash
npm run cf:deploy
```
--------------------------------
### 配置管理员邮箱环境变量
Source: https://docs.shipany.ai/zh/admin-system/admin
在 .env.development 文件中设置 ADMIN_EMAILS,多个邮箱地址使用英文逗号分隔。
```text
ADMIN_EMAILS = "xxx@gmail.com,user@xxx.com";
```
--------------------------------
### Payment URLs Configuration
Source: https://docs.shipany.ai/zh
Set the URLs for payment success, failure, and cancellation.
```env
NEXT_PUBLIC_PAY_SUCCESS_URL = "http://localhost:3000/my-orders"
NEXT_PUBLIC_PAY_FAIL_URL = "http://localhost:3000/#pricing"
NEXT_PUBLIC_PAY_CANCEL_URL = "http://localhost:3000/#pricing"
```
--------------------------------
### 使用 OpenAI 生成图片
Source: https://docs.shipany.ai/zh/ai-integrations/image-generation
通过 dall-e-3 模型生成图片,支持自定义质量和风格参数。
```typescript
import { experimental_generateImage as generateImage } from "ai";
import { openai } from "@ai-sdk/openai";
const prompt = "a beautiful girl running with 2 cats";
const model = "dall-e-3";
const imageModel = openai.image(model);
const providerOptions = {
openai: {
quality: "hd",
style: "natural",
},
};
const { images, warnings } = await generateImage({
model: imageModel,
prompt: prompt,
n: 1,
providerOptions,
});
```
--------------------------------
### Configure OpenPanel Client ID
Source: https://docs.shipany.ai/zh/features/analytics
Paste your OpenPanel Client ID into the .env.production file to enable OpenPanel statistics.
```env
NEXT_PUBLIC_OPENPANEL_CLIENT_ID = "xxx-xxx-xxx-xxx"
```
--------------------------------
### 实现多提供商 API 文本生成接口
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
创建一个统一的 API 路由,根据请求参数动态切换不同的 AI 提供商和模型。
```typescript
import { LanguageModelV1, generateText } from "ai";
import { respData, respErr } from "@/lib/resp";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import { openai } from "@ai-sdk/openai";
export async function POST(req: Request) {
try {
const { prompt, provider, model } = await req.json();
if (!prompt || !provider || !model) {
return respErr("invalid params");
}
let textModel: LanguageModelV1;
switch (provider) {
case "openai":
textModel = openai(model);
break;
case "openrouter":
const openrouter = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
textModel = openrouter(model);
break;
case "zhipu":
const zhipu = createOpenAICompatible({
name: "zhipu",
apiKey: process.env.ZHIPU_API_KEY,
baseURL: process.env.ZHIPU_BASE_URL,
});
textModel = zhipu(model);
break;
default:
return respErr("invalid provider");
}
const { text, warnings } = await generateText({
model: textModel,
prompt: prompt,
});
if (warnings && warnings.length > 0) {
console.log("gen text warnings:", provider, warnings);
return respErr("gen text failed");
}
return respData(text);
} catch (err) {
console.log("gen text failed:", err);
return respErr("gen text failed");
}
}
```
--------------------------------
### View Single Blog Post
Source: https://docs.shipany.ai/zh/features/blog
URL format to view a specific blog post. Replace {your-domain}, {locale}, and {slug} with the appropriate values.
```url
https://{your-domain}/{locale}/posts/{slug}
```
--------------------------------
### Configure Stripe Test Environment Variables
Source: https://docs.shipany.ai/zh/features/payment/stripe
Set up environment variables for local testing with Stripe. This includes the publishable key, private key, and webhook signing secret.
```dotenv
STRIPE_PUBLIC_KEY = "pk_test_xxx"
STRIPE_PRIVATE_KEY = "sk_test_xxx"
STRIPE_WEBHOOK_SECRET = "whsec_xxx"
```
--------------------------------
### 配置 Resend 环境变量
Source: https://docs.shipany.ai/zh/features/email/resend
在 .env.development 或 .env.production 文件中设置 API 密钥与发件人邮箱。
```text
RESEND_API_KEY = "re_xxx"
RESEND_SENDER_EMAIL = "contact@mail.shipany.ai"
```
--------------------------------
### 配置 Drizzle Kit 数据库连接
Source: https://docs.shipany.ai/zh/features/database
在 drizzle.config.ts 中定义数据库迁移路径、Schema 文件及连接凭据。确保环境变量 DATABASE_URL 已正确设置。
```typescript
import "dotenv/config";
import { config } from "dotenv";
import { defineConfig } from "drizzle-kit";
config({ path: ".env" });
config({ path: ".env.development" });
config({ path: ".env.local" });
export default defineConfig({
out: "./src/db/migrations",
schema: "./src/db/schema.ts",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
```
--------------------------------
### 发送模板邮件
Source: https://docs.shipany.ai/zh/features/email/resend
使用 react 参数传入定义的模板组件进行邮件发送。
```typescript
import { Resend } from "resend";
import { VerifyCode } from "@/components/email-templates/verify-code";
const resend = new Resend(process.env.RESEND_API_KEY!);
const result = await resend.emails.send({
from: process.env.RESEND_SENDER_EMAIL!,
to: ["test@mail.shipany.ai"],
subject: "Hello from ShipAny with Resend",
react: VerifyCode({ code: "123456" }),
});
console.log("send email result", result);
```
--------------------------------
### 配置 Replicate 环境变量
Source: https://docs.shipany.ai/zh/ai-integrations/image-generation
设置 Replicate API 的访问令牌。
```text
REPLICATE_API_TOKEN = "r8_xxx"
```
--------------------------------
### 保存生成的视频到本地
Source: https://docs.shipany.ai/zh/ai-integrations/video-generation
将 generateVideo 返回的 base64 编码视频数据转换为 Buffer 并写入本地文件系统。
```typescript
const { videos, warnings } = await generateVideo({
model: videoModel,
prompt: prompt,
n: 1,
providerOptions,
});
if (warnings.length > 0) {
console.log("gen videos warnings:", provider, warnings);
return respErr("gen videos failed");
}
const batch = getUuid();
const processedImages = await Promise.all(
videos.map(async (video, index) => {
const fileName = `${provider}_video_${batch}_${index}.mp4`;
const filePath = path.join(process.cwd(), ".tmp", fileName);
const buffer = Buffer.from(video.base64, "base64");
await writeFile(filePath, buffer);
return {
provider,
fileName,
filePath,
};
})
);
```
--------------------------------
### 使用 OpenAI 模型生成文本
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
通过 @ai-sdk/openai 调用 OpenAI 模型生成文本内容。
```typescript
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
const prompt = "who are you?";
const model = "gpt-4o";
const textModel = openai(model);
const { text, warnings } = await generateText({
model: textModel,
prompt: prompt,
});
if (warnings && warnings.length > 0) {
throw new Error("gen text failed");
}
console.log("gen text ok:", text);
```
--------------------------------
### 在页面中引入新组件
Source: https://docs.shipany.ai/zh/tutorials/new-components
在 Next.js 页面文件中导入并渲染自定义组件,同时设置运行时环境。
```tsx
import { LoginForm } from "@/components/new-component";
export const runtime = "edge";
export default function NewPage() {
return (
);
}
```
--------------------------------
### 实现流式文本生成 API
Source: https://docs.shipany.ai/zh/ai-integrations/chat-completions
通过 POST 请求接收 prompt、provider 和 model 参数,并使用 streamText 返回流式响应。需确保环境变量中已配置对应的 API Key。
```typescript
import { LanguageModelV1, streamText } from "ai";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import { openai } from "@ai-sdk/openai";
import { respErr } from "@/lib/resp";
export async function POST(req: Request) {
try {
const { prompt, provider, model } = await req.json();
if (!prompt || !provider || !model) {
return respErr("invalid params");
}
let textModel: LanguageModelV1;
switch (provider) {
case "openai":
textModel = openai(model);
break;
case "openrouter":
const openrouter = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
textModel = openrouter(model);
break;
case "zhipu":
const zhipu = createOpenAICompatible({
name: "zhipu",
apiKey: process.env.ZHIPU_API_KEY,
baseURL: process.env.ZHIPU_BASE_URL,
});
textModel = zhipu(model);
break;
default:
return respErr("invalid provider");
}
const result = await streamText({
model: textModel,
prompt: prompt,
onFinish: async () => {
console.log("finish", await result.text);
},
});
return result.toTextStreamResponse();
} catch (err) {
console.log("gen text stream failed:", err);
return respErr("gen text stream failed");
}
}
```
--------------------------------
### Implement Custom Hero in Page
Source: https://docs.shipany.ai/zh/components/hero
Use the Hero component by passing a data object that conforms to the Hero interface. Ensure the component is imported from the correct path.
```typescript
import Hero from "@/components/blocks/hero";
import { Hero as HeroType } from "@/types/blocks/hero";
export default function Page() {
// custom hero data
const hero: HeroType = {
title: "Ship Any AI Startups in hours, not days",
highlight_text: "Ship Any",
description:
"ShipAny is a NextJS boilerplate for building AI SaaS startups.
Ship Fast with a variety of templates and components.",
announcement: {
title: "🎉 Happy New Year",
url: "/#pricing",
},
buttons: [
{
title: "Get ShipAny",
url: "/ai-podcast-generator",
},
],
show_happy_users: true,
};
return <>
// ...other components
>
);
}
```
--------------------------------
### 自定义支付返佣逻辑
Source: https://docs.shipany.ai/zh/features/affiliate
在 services/affiliate.ts 中修改 updateAffiliateForOrder 方法,以调整用户支付成功后的返佣奖励规则。
```typescript
import { findAffiliateByOrderNo, insertAffiliate } from "@/models/affiliate";
import { AffiliateRewardAmount } from "./constant";
import { AffiliateRewardPercent } from "./constant";
import { AffiliateStatus } from "./constant";
import { Order } from "@/types/order";
import { findUserByUuid } from "@/models/user";
import { getIsoTimestr } from "@/lib/time";
export async function updateAffiliateForOrder(order: Order) {
try {
const user = await findUserByUuid(order.user_uuid);
if (user && user.uuid && user.invited_by && user.invited_by !== user.uuid) {
const affiliate = await findAffiliateByOrderNo(order.order_no);
if (affiliate) {
return;
}
await insertAffiliate({
user_uuid: user.uuid,
invited_by: user.invited_by,
created_at: getIsoTimestr(),
status: AffiliateStatus.Completed,
paid_order_no: order.order_no,
paid_amount: order.amount,
reward_percent: AffiliateRewardPercent.Paied,
reward_amount: AffiliateRewardAmount.Paied,
});
}
} catch (e) {
console.log("update affiliate for order failed: ", e);
throw e;
}
}
```
--------------------------------
### 生成隐私政策提示词
Source: https://docs.shipany.ai/zh/tutorials/edit-agreement
使用此提示词在 Cursor 中生成基于现有内容的隐私政策。
```text
update privacy-policy according to landing page content @en.json
with brand name "ShipAny", domain "shipany.ai", contact email is "support@shipany.ai"
```
--------------------------------
### Create New Local Branch
Source: https://docs.shipany.ai/zh/guide/faq
Use this command to create a new local branch for backing up the current state of the main branch.
```bash
git checkout -b backup
```
--------------------------------
### 全局安装 pnpm
Source: https://docs.shipany.ai/zh/guide/good-to-know
使用 npm 全局安装 pnpm 包管理器。
```bash
$ npm install -g pnpm
```
--------------------------------
### 使用 OpenRouter 聚合模型生成文本
Source: https://docs.shipany.ai/zh/ai-integrations/text-generation
通过 @openrouter/ai-sdk-provider 调用 OpenRouter 平台上的模型。
```typescript
import { generateText } from "ai";
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
const openrouter = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
const prompt = "who are you?";
const model = "deepseek/deepseek-r1";
const textModel = openrouter(model);
const { text, warnings } = await generateText({
model: textModel,
prompt: prompt,
});
if (warnings && warnings.length > 0) {
throw new Error("gen text failed");
}
console.log("gen text ok:", text);
```
--------------------------------
### AI 辅助组件生成提示词
Source: https://docs.shipany.ai/zh/tutorials/new-components
在 Cursor 中使用截图和提示词生成基于 shadcn/ui 和 tailwindcss 的 React 组件。
```text
follow this screenshot, create a react function component for me, use shadcn/ui, tailwindcss
```
--------------------------------
### Landing Page Content Generation Prompt
Source: https://docs.shipany.ai/zh/features/i18n
This prompt can be used to generate or update landing page content for your product, referencing the product name and a relevant URL.
```plaintext
I want to build a landing page for my product named "Flux AI Image Generator", please update the landing page json file, content reference @Web @https://www.flux.ai/
```
--------------------------------
### 上传 AI 生成的 Base64 图片
Source: https://docs.shipany.ai/zh/features/storage
将 Base64 编码的图片数据转换为 Buffer 并上传至云存储。
```typescript
import { newStorage } from "@/lib/storage";
const storage = new Storage();
const filename = `image_${new Date().getTime()}.png`;
const key = `shipany/${filename}`;
const body = Buffer.from(image.base64, "base64");
try {
const res = await storage.uploadFile({
body,
key,
contentType: "image/png",
disposition: "inline",
});
console.log("upload file success:", res);
} catch (err) {
console.log("upload file failed:", err);
}
```
--------------------------------
### AI-Assisted Content Generation Prompt
Source: https://docs.shipany.ai/zh/features/i18n
Use this prompt to have AI assist in generating or updating content for your i18n JSON files, specifying the project name and keywords.
```plaintext
update content of this file, for my new project "Flux AI", which is an AI Image Generator, with keywords "flux ai, ai image generator"
```
--------------------------------
### Locale Detection Configuration
Source: https://docs.shipany.ai/zh
Configure locale detection for the application.
```env
NEXT_PUBLIC_LOCALE_DETECTION = "false"
```
--------------------------------
### 配置谷歌登录回调 URL
Source: https://docs.shipany.ai/zh/features/oauth
根据项目运行环境配置谷歌登录的回调 URL。本地调试使用 http://localhost:3000/api/auth/callback/google,线上环境使用 https://{your-domain}/api/auth/callback/google。
```plaintext
http://localhost:3000/api/auth/callback/google
```
```plaintext
https://{your-domain}/api/auth/callback/google
```
--------------------------------
### ShipAny Environment Configuration for Stripe
Source: https://docs.shipany.ai/zh/features/payment/stripe
Configure Stripe payment gateway details in your ShipAny project's environment files. Ensure `PAY_PROVIDER` is set to 'stripe' and provide your Stripe publishable key, secret key, and webhook secret.
```env
NEXT_PUBLIC_WEB_URL = "http://localhost:3000"
NEXT_PUBLIC_PAY_SUCCESS_URL = "/my-orders"
NEXT_PUBLIC_PAY_FAIL_URL = "/pricing"
NEXT_PUBLIC_PAY_CANCEL_URL = "/pricing"
PAY_PROVIDER = "stripe"
STRIPE_PUBLIC_KEY = "pk_test_xxx"
STRIPE_PRIVATE_KEY = "sk_test_xxx"
STRIPE_WEBHOOK_SECRET = "whsec_cexxx"
```
--------------------------------
### 生成服务条款提示词
Source: https://docs.shipany.ai/zh/tutorials/edit-agreement
使用此提示词在 Cursor 中生成基于现有内容的服务条款。
```text
update terms-of-service according to landing page content @en.json
with brand name "ShipAny", domain "shipany.ai", contact email is "support@shipany.ai"
```
--------------------------------
### 数据库连接字符串示例
Source: https://docs.shipany.ai/zh/features/database
从 Supabase 控制台获取的数据库连接字符串格式。
```text
postgresql://postgres.defqvdpquwyqqjlmurkg:[YOUR-PASSWORD]@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
```