From bd88c75990545bcd2959898d2b46f1e5c45149fa Mon Sep 17 00:00:00 2001 From: fanxiao Date: Sat, 18 Oct 2025 14:18:15 +0900 Subject: [PATCH 1/2] 20251018 --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ task.md | 24 ++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 task.md diff --git a/README.md b/README.md index 093d91d2e..a90fc1541 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,43 @@ pnpm install stripe login ``` +去vercel上面申请了neon-green-chair免费版的数据库,并尝试建立本地连接,方便下一步部署 + Use the included setup script to create your `.env` file: ```bash pnpm db:setup ``` +```bash +pnpm db:setup + +> @ db:setup C:\Users\FX\IdeaProjects\fx-saas +> npx tsx lib/db/setup.ts + +Step 1: Checking if Stripe CLI is installed and authenticated... +Stripe CLI is installed. +Stripe CLI is authenticated. +Step 2: Setting up Postgres +Do you want to use a local Postgres instance with Docker (L) or a remote Postgres instance (R)? (L/R): R 选择R远程数据库 +You can find Postgres databases at: https://vercel.com/marketplace?category=databases +Enter your POSTGRES_URL: 去vercel上面申请了neon-green-chair免费版的数据库,并尝试建立本地连接 +Step 3: Getting Stripe Secret Key +You can find your Stripe Secret Key at: https://dashboard.stripe.com/test/apikeys +Enter your Stripe Secret Key: 去该网站申请测试KEY https://dashboard.stripe.com/acct_1SIrbsICXUfDaKJj/test/apikeys +Step 4: Creating Stripe webhook... +Stripe webhook created. +Step 5: Generating AUTH_SECRET... +Stripe webhook created. +Step 5: Generating AUTH_SECRET... +Step 6: Writing environment variables to .env +.env file created with the necessary variables. +🎉 Setup completed successfully! +Step 6: Writing environment variables to .env +.env file created with the necessary variables. +🎉 Setup completed successfully! +🎉 Setup completed successfully! +``` Run the database migrations and seed the database with a default user and team: ```bash @@ -74,6 +105,28 @@ You can listen for Stripe webhooks locally through their CLI to handle subscript stripe listen --forward-to localhost:3000/api/stripe/webhook ``` +登录 Stripe Dashboard +👉 https://dashboard.stripe.com/test/webhooks + +点击「+ Add endpoint」 + +输入你的 Webhook 地址,例如: + +https://fx-saas.vercel.app/api/stripe/webhook + + +选择要监听的事件(例如 checkout.session.completed, invoice.paid 等) +创建成功后,页面会显示一个类似: + +whsec_live_xxx + + +的 Signing secret + +将它填入线上环境变量(Vercel 的 Dashboard → Project → Settings → Environment Variables): + +STRIPE_WEBHOOK_SECRET=whsec_live_xxx + ## Testing Payments To test Stripe payments, use the following test card details: @@ -98,6 +151,8 @@ When you're ready to deploy your SaaS application to production, follow these st 2. Connect your repository to [Vercel](https://vercel.com/) and deploy it. 3. Follow the Vercel deployment process, which will guide you through setting up your project. +进入 Vercel 项目的 Settings → Environment Variables建立环境变量,导入本地env文件即可 + ### Add environment variables In your Vercel project settings (or during deployment), add all the necessary environment variables. Make sure to update the values for the production environment, including: diff --git a/task.md b/task.md new file mode 100644 index 000000000..271506332 --- /dev/null +++ b/task.md @@ -0,0 +1,24 @@ +20251017: +本地部署成功 +vercel 部署成功 +vercel申请了pgsqlDB成功 +申请了stripe账户和密钥 +理解了stripe支付的webhook,并与本地连接成功 +npm run db:generate -- lib/db/schema.ts +npm run db:migrate -- lib/db/migrations/sql脚本执行 +以上两个命令的使用场景是新增表-新业务情况 +---------------------------------------------- +Let's Encrypt 是免费的证书颁发机构(CA),可以帮你申请 免费 SSL 证书。 +配合 Nginx,可以自动配置 HTTPS,浏览器和 Stripe 都能正常访问。 +命令解释: +yum install -y certbot python3-certbot-nginx # 安装 Certbot 工具和 Nginx 插件 +certbot --nginx -d your-domain.com # 生成证书并自动修改 Nginx 配置 +---------------------------------------------- + + + + +下一个阶段是尝试部署到serv00服务器或其他服务器 +尝试开发几个页面 +尝试开发几个接口 +尝试直接访问接口 From c542b9bf65c3b69859fc7cb59f97afb347ad1d72 Mon Sep 17 00:00:00 2001 From: fanxiao Date: Sun, 19 Oct 2025 23:56:32 +0900 Subject: [PATCH 2/2] =?UTF-8?q?dashboard=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(dashboard)/layout.tsx | 2 +- app/(dashboard)/page.tsx | 59 +++++++++++++++++++++--------------- app/(dashboard)/terminal.tsx | 15 ++++----- app/(login)/login.tsx | 16 +++++----- app/layout.tsx | 29 +++++++++++++++--- app/not-found.tsx | 10 ++++++ 6 files changed, 86 insertions(+), 45 deletions(-) diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx index 5e1d0b1b2..340644b67 100644 --- a/app/(dashboard)/layout.tsx +++ b/app/(dashboard)/layout.tsx @@ -84,7 +84,7 @@ function Header() {
- ACME + FanXiao
}> diff --git a/app/(dashboard)/page.tsx b/app/(dashboard)/page.tsx index 07e3b487f..71930df56 100644 --- a/app/(dashboard)/page.tsx +++ b/app/(dashboard)/page.tsx @@ -1,5 +1,10 @@ import { Button } from '@/components/ui/button'; -import { ArrowRight, CreditCard, Database } from 'lucide-react'; +import { + BookOpen, // 📖 书籍 - 诗歌/文学 + Clapperboard, // 🎬 电影板 - 导演梦想 + Heart, // 💖 爱心 - 浪漫主义 + ArrowRight +} from 'lucide-react'; import { Terminal } from './terminal'; export default function HomePage() { @@ -10,13 +15,11 @@ export default function HomePage() {

- Build Your SaaS - Faster Than Ever + 欢迎来到我的网站 + 你今天开心吗?

- Launch your SaaS product in record time with our powerful, - ready-to-use template. Packed with modern technologies and - essential integrations. + 把你不开心的事情说出来,让大家开心一下

- Deploy your own + 这是一个跳转连接 @@ -46,46 +49,56 @@ export default function HomePage() {
- + {/* - + */} +

- Next.js and React + 樊宵

- Leverage the power of modern web technologies for optimal - performance and developer experience. + 时代浪漫主义诗人 • 作家 • 学者

+
+
+ 足球巨星不是梦 +
+
+ 🎬 未来导演是行动 +
+
+ ✍️ 浪漫主义实践者 +
+
- +

- Postgres and Drizzle ORM + 探索我的世界

- Robust database solution with an intuitive ORM for efficient - data management and scalability. + 在时代浪潮中,追寻诗意的足球,在光影之间,书写浪漫的导演梦

- +

- Stripe Integration + 阅读诗集

Seamless payment processing and subscription management with @@ -102,12 +115,10 @@ export default function HomePage() {

- Ready to launch your SaaS? + 诗是流动的光影,梦是无尽的绿茵。

- Our template provides everything you need to get your SaaS up - and running quickly. Don't waste time on boilerplate - focus on - what makes your product unique. + 这里是我的个人诗歌集与梦想日志——时代浪漫主义的片段与隽语,亦或足球场上的奔跑和电影镜头下的故事。

@@ -117,7 +128,7 @@ export default function HomePage() { variant="outline" className="text-lg rounded-full" > - View the code + 联系我 diff --git a/app/(dashboard)/terminal.tsx b/app/(dashboard)/terminal.tsx index a80112317..e81fc11c4 100644 --- a/app/(dashboard)/terminal.tsx +++ b/app/(dashboard)/terminal.tsx @@ -7,20 +7,21 @@ export function Terminal() { const [terminalStep, setTerminalStep] = useState(0); const [copied, setCopied] = useState(false); const terminalSteps = [ - 'git clone https://github.com/nextjs/saas-starter', - 'pnpm install', - 'pnpm db:setup', - 'pnpm db:migrate', - 'pnpm db:seed', - 'pnpm dev 🎉', + '樊宵 · 时代诗人', + '逐梦足球场', + '光影导演人生', + '浪漫主义的自由书写', + '"诗,是流动的光影与不灭的梦想"', + '—— 你好,世界 🎉', ]; + useEffect(() => { const timer = setTimeout(() => { setTerminalStep((prev) => prev < terminalSteps.length - 1 ? prev + 1 : prev ); - }, 500); + }, 1000); return () => clearTimeout(timer); }, [terminalStep]); diff --git a/app/(login)/login.tsx b/app/(login)/login.tsx index 86c7e280d..c9dca9742 100644 --- a/app/(login)/login.tsx +++ b/app/(login)/login.tsx @@ -1,14 +1,14 @@ -'use client'; +'use client';// 声明这是前端组件,支持事件和交互 -import Link from 'next/link'; -import { useActionState } from 'react'; -import { useSearchParams } from 'next/navigation'; -import { Button } from '@/components/ui/button'; +import Link from 'next/link';// 跳转路由 +import { useActionState } from 'react';// React 18 的表单处理新钩子 +import { useSearchParams } from 'next/navigation';// 读取URL参数,支持跳转、邀请等 +import { Button } from '@/components/ui/button';// 引入项目自定义UI组件 import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -import { CircleIcon, Loader2 } from 'lucide-react'; -import { signIn, signUp } from './actions'; -import { ActionState } from '@/lib/auth/middleware'; +import { CircleIcon, Loader2 } from 'lucide-react';// 图标,用于美化UI +import { signIn, signUp } from './actions';// 导入实际登录/注册逻辑(应该是 server actions) +import { ActionState } from '@/lib/auth/middleware';// 状态类型定义 export function Login({ mode = 'signin' }: { mode?: 'signin' | 'signup' }) { const searchParams = useSearchParams(); diff --git a/app/layout.tsx b/app/layout.tsx index 9c2596780..31c62bf4f 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,28 +1,45 @@ +// 引入全局样式表,作用于整个 APP import './globals.css'; +// 导入 Next.js 中 Metadata(页面元信息)、Viewport 类型(用于响应式) import type { Metadata, Viewport } from 'next'; -import { Manrope } from 'next/font/google'; +// 导入 Google Fonts 字体加载器(Manrope 字体) +import { Noto_Sans_SC, Noto_Sans_JP, Manrope } from 'next/font/google'; +// 导入用户/团队获取工具函数(通常用于数据预加载或 fallback 数据) import { getUser, getTeamForUser } from '@/lib/db/queries'; +// 导入 SWR 的全局 Provider,用于统一缓存和数据请求配置 import { SWRConfig } from 'swr'; +// 配置页面的基础元数据(SEO 标题、简介、分享描述等) export const metadata: Metadata = { - title: 'Next.js SaaS Starter', - description: 'Get started quickly with Next.js, Postgres, and Stripe.' + title: 'FX', + description: '樊宵(Fan Xiao),专注于AI与程序设计融合的创新开发,打造中日跨境B2B服务与智能化系统,让技术与创造力共同驱动未来。' }; +// 配置移动端 viewport 行为,这里禁止页面最大缩放超过 1(防止用户手动放大页面) export const viewport: Viewport = { maximumScale: 1 }; -const manrope = Manrope({ subsets: ['latin'] }); +// 加载 Manrope Web 字体,仅拉取 'latin'(英文字母)子集以加速加载 +const manrope = Manrope({ subsets: ['latin'] , display: 'swap' }); +const jp = Noto_Sans_JP({ display: 'swap' }); +const sc = Noto_Sans_SC({ display: 'swap' }); +/** + * RootLayout 是所有页面外层的全局布局组件 + * @param children 所有实际页面内容会被当做 children 进行渲染 + */ export default function RootLayout({ children }: { children: React.ReactNode; }) { return ( + // 设置网页语言为英语 html 元素,并加入自定义字体样式 + // 网站主体 body 设置亮/暗色主题自动切换 + // SWRConfig 配置全局数据缓存/fallback(首屏异步数据预热),所有子组件都能用 @@ -31,11 +48,13 @@ export default function RootLayout({ fallback: { // We do NOT await here // Only components that read this data will suspend + // 这里不 await,getUser() 和 getTeamForUser() 返回的是 Promise,只有真正用到才开始 suspend 等待 '/api/user': getUser(), '/api/team': getTeamForUser() } }} > + {/* 渲染页面实际内容(即各路由对应的页面组件) */} {children} diff --git a/app/not-found.tsx b/app/not-found.tsx index 7aad74b69..1474d2e3e 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -1,20 +1,30 @@ +// 导入 Next.js 的 Link 组件,用于跳转到首页或其他正确路由 import Link from 'next/link'; +// 导入 lucide-react 图标库的 CircleIcon,作为页面视觉提示 import { CircleIcon } from 'lucide-react'; +/** + * NotFound 组件是 Next.js app 路由下自动识别的 404 页面 + * 任何不存在的地址都会自动渲染这里的内容 + */ export default function NotFound() { return (
+ {/* 圆形图标,增加错误提示的视觉效果 */}
+ {/* 主要错误标题,清晰告知用户页面未找到 */}

Page Not Found

+ {/* 错误原因解释,帮助用户理解可能发生的问题 */}

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

+ {/* 提供返回首页链接,帮助用户自救继续访问 */}