### Start Development Server Source: https://docs.shipany.ai/zh Launch the local development server to preview your project. ```bash pnpm dev ``` -------------------------------- ### Install Project Dependencies Source: https://docs.shipany.ai/zh Install all necessary project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Copy Environment Configuration Source: https://docs.shipany.ai/zh Create a development environment configuration file by copying the example file. ```bash cp .env.example .env.development ``` -------------------------------- ### Example Environment Configuration Source: https://docs.shipany.ai/zh Sample configuration for development and production environments, including web information, database, authentication, and analytics. ```dotenv # ----------------------------------------------------------------------------- # Web Information # ----------------------------------------------------------------------------- NEXT_PUBLIC_WEB_URL = "http://localhost:3000" NEXT_PUBLIC_PROJECT_NAME = "ShipAny" # ----------------------------------------------------------------------------- # Database with Supabase # ----------------------------------------------------------------------------- # https://supabase.com/docs/guides/getting-started/quickstarts/nextjs # Set your Supabase DATABASE_URL DATABASE_URL = "" # ----------------------------------------------------------------------------- # Auth with next-auth # https://authjs.dev/getting-started/installation?framework=Next.js # Set your Auth URL and Secret # Secret can be generated with `openssl rand -base64 32` # ----------------------------------------------------------------------------- AUTH_SECRET = "Zt3BXVudzzRq2R2WBqhwRy1dNMq48Gg9zKAYq7YwSL0=" AUTH_URL = "http://localhost:3000/api/auth" AUTH_TRUST_HOST = true # Google Auth # https://authjs.dev/getting-started/providers/google AUTH_GOOGLE_ID = "" AUTH_GOOGLE_SECRET = "" NEXT_PUBLIC_AUTH_GOOGLE_ID = "" NEXT_PUBLIC_AUTH_GOOGLE_ENABLED = "false" NEXT_PUBLIC_AUTH_GOOGLE_ONE_TAP_ENABLED = "false" # Github Auth # https://authjs.dev/getting-started/providers/github AUTH_GITHUB_ID = "" AUTH_GITHUB_SECRET = "" NEXT_PUBLIC_AUTH_GITHUB_ENABLED = "false" # ----------------------------------------------------------------------------- # Analytics with Google Analytics # https://analytics.google.com # ----------------------------------------------------------------------------- NEXT_PUBLIC_GOOGLE_ANALYTICS_ID = "" # ----------------------------------------------------------------------------- # Analytics with OpenPanel # https://openpanel.dev # ----------------------------------------------------------------------------- NEXT_PUBLIC_OPENPANEL_CLIENT_ID = "" # Analytics with Plausible # https://plausible.io/ NEXT_PUBLIC_PLAUSIBLE_DOMAIN = "" NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL = "" ``` -------------------------------- ### Start ngrok for Local Webhook Testing Source: https://docs.shipany.ai/zh/features/payment/stripe Use ngrok to expose your local development server to the internet, allowing Stripe to send webhook notifications to your local machine. This command starts ngrok listening on port 3000. ```bash ngrok http http://localhost:3000 ``` -------------------------------- ### Create a New API Endpoint in ShipAny Source: https://docs.shipany.ai/zh/tutorials/api-call Implement API business logic by creating a `route.ts` file within the `app/api` directory. This example demonstrates a simple POST request handler. ```typescript import { respData, respErr } from "@/lib/resp"; export async function POST(req: Request) { try { const { message } = await req.json(); if (!message) { return respErr("invalid params"); } return respData({ pong: `received message: ${message}`, }); } catch (e) { console.log("test failed:", e); return respErr("test failed"); } } ``` -------------------------------- ### Testimonial Component Usage Source: https://docs.shipany.ai/zh/components/testimonial Example of how to use the Testimonial component in a page, including custom data. ```APIDOC ## Testimonial Component Usage ### Description This section shows how to import and use the `Testimonial` component within a React page. It includes an example of defining custom testimonial data that conforms to the `TestimonialType`. ### Method ```typescript import Testimonial from "@/components/blocks/testimonial"; import { Testimonial as TestimonialType } from "@/types/blocks/testimonial"; export default function Page() { // custom Testimonial data const testimonial: TestimonialType = { "title": "What Users Say About ShipAny", "description": "Hear from developers and founders who launched their AI startups with ShipAny.", "items": [ { "avatar": { "src": "/imgs/user/1.png" }, "name": "David Chen", "title": "Founder of AIWallpaper.shop", "comment": "ShipAny saved us months of development time. We launched our AI business in just 2 days and got our first paying customer within a week!", }, // ...other testimonials ], }; return <> // ...other components ; } ``` ``` -------------------------------- ### CTA Component Usage Source: https://docs.shipany.ai/zh/components/cta Example of how to use the CTA component in a page, including custom data. ```APIDOC ## CTA Component Usage Example ### Description This section demonstrates how to import and use the CTA component within a React page. It includes defining custom CTA data that conforms to the `CTAType`. ### Method Component Usage ### Endpoint N/A (Client-side component) ### Request Body N/A ### Request Example ```jsx import CTA from "@/components/blocks/cta"; import { CTA as CTAType } from "@/types/blocks/cta"; export default function Page() { // custom CTA data const cta: CTAType = { "title": "Ship your first AI SaaS Startup", "description": "Start from here, with ShipAny.", "buttons": [ { "title": "Get ShipAny", "url": "/#pricing" } ] } return <> // ...other components ; } ``` ### Response N/A (Client-side component rendering) ``` -------------------------------- ### Implement Custom Header in Page Source: https://docs.shipany.ai/zh/components/header Example of how to implement a custom header in a page component using the Header component and its type definition. Ensure the Header component and its types are correctly imported. ```tsx import Header from "@/components/blocks/header"; import { Header as HeaderType } from "@/types/blocks/header"; export default function Page() { // custom header data const header: HeaderType = { logo: { title: "ShipAny", image: { src: "/logo.png", alt: "ShipAny", }, }, nav: { items: [ { title: "Features", href: "/features", }, { title: "Pricing", href: "/pricing", }, { title: "Showcases", children: [ { title: "Showcase 1", href: "/showcase/1", }, { title: "Showcase 2", href: "/showcase/2", }, ], }, ], }, buttons: [ { title: "Sign In", variant: "primary", href: "/auth/signin", }, ], }; return ( <>
// ...other components ); } ``` -------------------------------- ### Navigate to Project Directory Source: https://docs.shipany.ai/zh Change your current directory to the root of the cloned ShipAny project. ```bash cd my-shipany-project ``` -------------------------------- ### 创建生产环境配置文件 Source: https://docs.shipany.ai/zh/deploy/deploy-to-cloudflare 从示例文件复制并创建生产环境所需的 .env.production 文件。 ```bash cp .env.example .env.production ``` -------------------------------- ### 配置 OpenAI API 环境变量 Source: https://docs.shipany.ai/zh/ai-integrations/text-generation 在 .env 文件中设置 OpenAI API Key 以进行身份验证。 ```env OPENAI_API_KEY = "sk-xxx"; ``` -------------------------------- ### Get User Orders by UUID Source: https://docs.shipany.ai/zh/user-console/new-table Retrieves a list of paid orders for a specific user from the database, ordered by creation date. ```typescript export async function getOrdersByUserUuid( user_uuid: string ): Promise { 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 ```