refactor: rename project DADA → 云梦 (slug: yume)
- 所有 workspace 包 @dada/* → @yume/*,根包 dada → yume - 全部导入路径同步更新 - 内部 ID 对齐:dada-ripple → yume-ripple,dada:custom → yume:custom - 首页 / new / play 用户文案整段中文化,保留 smallcaps + 衬线 + 罗马数字排版语汇 - README 标题改为 "# 云梦",部署链接与目录树 slug 改为 yume - 重新生成 pnpm-lock.yaml Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# =============================================================
|
||||
# Dada — AI Visual Novel
|
||||
# 云梦 — AI 视觉小说
|
||||
# Three independently configurable AI providers
|
||||
# Any OpenAI-compatible endpoint works (OpenRouter, OpenAI,
|
||||
# Anthropic via OpenAI-compat proxy, Gemini, DeepSeek, Ollama).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { takeTurn } from "@dada/engine";
|
||||
import type { InteractRequest } from "@dada/types";
|
||||
import { takeTurn } from "@yume/engine";
|
||||
import type { InteractRequest } from "@yume/types";
|
||||
import { NextResponse } from "next/server";
|
||||
import { loadEngineConfig } from "@/lib/config";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { startSession } from "@dada/engine";
|
||||
import type { StartRequest } from "@dada/types";
|
||||
import { startSession } from "@yume/engine";
|
||||
import type { StartRequest } from "@yume/types";
|
||||
import { NextResponse } from "next/server";
|
||||
import { loadEngineConfig } from "@/lib/config";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { visionTurn } from "@dada/engine";
|
||||
import type { VisionRequest } from "@dada/types";
|
||||
import { visionTurn } from "@yume/engine";
|
||||
import type { VisionRequest } from "@yume/types";
|
||||
import { NextResponse } from "next/server";
|
||||
import { loadEngineConfig } from "@/lib/config";
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dada-ripple {
|
||||
@keyframes yume-ripple {
|
||||
0% {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
|
||||
@@ -2,9 +2,8 @@ import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Dada — AI Visual Novel",
|
||||
description:
|
||||
"An open-source visual novel where every frame is generated by AI.",
|
||||
title: "云梦 — AI 视觉小说",
|
||||
description: "一部由 AI 实时绘制每一帧的开源视觉小说。",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@@ -10,10 +10,10 @@ export default function NewPage() {
|
||||
className="text-[10px] smallcaps text-clay-700 hover:text-clay-900 transition-colors flex items-center gap-2"
|
||||
>
|
||||
<i className="fa-solid fa-arrow-left text-[9px]" />
|
||||
Dada
|
||||
云梦
|
||||
</Link>
|
||||
<span className="text-[10px] smallcaps text-clay-500">
|
||||
Compose · a · world
|
||||
编 织 一 个 世 界
|
||||
</span>
|
||||
</header>
|
||||
|
||||
@@ -21,23 +21,22 @@ export default function NewPage() {
|
||||
<div className="grid grid-cols-12 gap-8 md:gap-16 max-w-6xl">
|
||||
<div className="col-span-12 md:col-span-4 animate-fade-in">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-6">
|
||||
Ⅳ · Untitled
|
||||
Ⅳ · 无 题
|
||||
</p>
|
||||
<h1 className="font-serif text-[44px] md:text-[64px] text-clay-900 leading-[0.96] mb-8">
|
||||
Write
|
||||
写下
|
||||
<br />
|
||||
<em className="italic text-clay-600">two</em>
|
||||
<em className="italic text-clay-600">两段</em>
|
||||
<br />
|
||||
paragraphs.
|
||||
文字。
|
||||
</h1>
|
||||
<div className="hairline w-12 mb-6" />
|
||||
<p className="font-serif text-base text-clay-700 leading-[1.7]">
|
||||
The first sketches the world your story unfolds in. The second
|
||||
describes how the world should look — its medium, its mood, its
|
||||
grain.
|
||||
第一段,勾勒故事所在的世界。第二段,描述世界应是什么模样 —
|
||||
它的介质、氛围、颗粒感。
|
||||
</p>
|
||||
<p className="font-serif italic text-sm text-clay-500 mt-5 leading-relaxed">
|
||||
Both fields accept any language. Specificity rewards specificity.
|
||||
两栏皆可任意语言。越具体,回报越具体。
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-span-12 md:col-span-7 md:col-start-6">
|
||||
|
||||
+26
-29
@@ -10,11 +10,11 @@ export default function LandingPage() {
|
||||
<header className="px-6 md:px-16 pt-7 md:pt-10 flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-[10px] smallcaps text-clay-700 font-medium">
|
||||
Dada
|
||||
云梦
|
||||
</span>
|
||||
<span className="hairline w-10 hidden md:block" />
|
||||
<span className="text-[10px] smallcaps text-clay-500 hidden md:block">
|
||||
Frame · by · Frame
|
||||
逐 · 帧 · 而 · 成
|
||||
</span>
|
||||
</div>
|
||||
<nav className="flex items-center gap-5 text-[10px] smallcaps text-clay-600">
|
||||
@@ -26,7 +26,7 @@ export default function LandingPage() {
|
||||
</a>
|
||||
<span className="text-clay-300">·</span>
|
||||
<a href="#about" className="hover:text-clay-900 transition-colors">
|
||||
About
|
||||
关于
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -35,20 +35,19 @@ export default function LandingPage() {
|
||||
<div className="grid grid-cols-12 gap-8">
|
||||
<div className="col-span-12 md:col-span-7 animate-fade-in">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-8">
|
||||
An open-source experiment · MMXXVI
|
||||
一场 · 开源 · 实验 · MMXXVI
|
||||
</p>
|
||||
<h1 className="font-serif font-light text-[56px] md:text-[104px] leading-[0.94] text-clay-900 tracking-tight">
|
||||
Every{" "}
|
||||
<em className="italic font-light text-clay-600">frame</em>
|
||||
每<em className="italic font-light text-clay-600">一帧</em>
|
||||
<br />
|
||||
is painted on
|
||||
都于
|
||||
<br />
|
||||
<span className="text-ember-500 italic font-light">demand.</span>
|
||||
<span className="text-ember-500 italic font-light">此刻</span>
|
||||
诞生。
|
||||
</h1>
|
||||
<p className="mt-10 md:mt-14 max-w-md font-serif text-lg md:text-xl text-clay-700 leading-[1.65]">
|
||||
Dada is a visual novel where the <em>entire</em> interface — scene,
|
||||
dialogue, choices — is rendered by an AI, one frame at a time. You
|
||||
click. It paints. The story unfolds.
|
||||
云梦是一部视觉小说 — 场景、对话、选项,<em>整个</em>界面皆由 AI
|
||||
一帧一帧绘成。你点击。它落笔。故事铺展。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -56,13 +55,13 @@ export default function LandingPage() {
|
||||
<div className="space-y-3">
|
||||
<div className="hairline w-12" />
|
||||
<p className="font-serif italic text-clay-600 text-base md:text-[17px] leading-relaxed max-w-[280px]">
|
||||
“It is impossible to step into the same river twice.
|
||||
“人不能两次踏入同一条河流。
|
||||
</p>
|
||||
<p className="font-serif italic text-clay-600 text-base md:text-[17px] leading-relaxed max-w-[280px]">
|
||||
It is impossible to play the same Dada twice.”
|
||||
你也不会两次走进同一个云梦。”
|
||||
</p>
|
||||
<p className="text-[10px] smallcaps text-clay-500 pt-2">
|
||||
— README · v0.1
|
||||
— 自述 · v0.1
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -76,10 +75,10 @@ export default function LandingPage() {
|
||||
<section className="px-6 md:px-16 pt-14 md:pt-20 pb-16 md:pb-24">
|
||||
<div className="flex items-baseline justify-between mb-8 md:mb-10">
|
||||
<h2 className="text-[10px] smallcaps text-clay-700 font-medium">
|
||||
Four Doors
|
||||
四 扇 门
|
||||
</h2>
|
||||
<p className="text-[10px] smallcaps text-clay-500 hidden md:block">
|
||||
Choose a world · or compose your own
|
||||
择 一 世 界 · 或 自 行 编 织
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -98,14 +97,14 @@ export default function LandingPage() {
|
||||
</span>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="font-serif text-3xl md:text-4xl text-clay-900 leading-tight mb-2.5">
|
||||
Untitled
|
||||
无 题
|
||||
</h3>
|
||||
<p className="text-sm text-clay-600 leading-relaxed max-w-md">
|
||||
Bring your own world. Describe it in your own words.
|
||||
带来你自己的世界。用你自己的话讲述它。
|
||||
</p>
|
||||
</div>
|
||||
<span className="hidden md:flex items-center gap-3 text-[10px] tracking-[0.4em] text-clay-400 group-hover:text-ember-500 transition-colors duration-500 shrink-0 self-center">
|
||||
COMPOSE
|
||||
编 织
|
||||
<span className="w-7 h-px bg-current transition-all duration-500 group-hover:w-12" />
|
||||
</span>
|
||||
</div>
|
||||
@@ -119,30 +118,28 @@ export default function LandingPage() {
|
||||
>
|
||||
<div className="col-span-12 md:col-span-3">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-3">
|
||||
Colophon · I
|
||||
题 跋 · I
|
||||
</p>
|
||||
<p className="font-serif italic text-clay-700 text-base leading-relaxed">
|
||||
A small open-source experiment in generative narrative. Self-host on
|
||||
Vercel in a single click.
|
||||
一场关于生成式叙事的小型开源实验。一键 Vercel 自建。
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-span-12 md:col-span-3 md:col-start-5">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-3">
|
||||
Colophon · II
|
||||
题 跋 · II
|
||||
</p>
|
||||
<ul className="font-serif text-clay-700 text-base leading-relaxed space-y-1">
|
||||
<li>Story · large language model</li>
|
||||
<li>Image · generative renderer</li>
|
||||
<li>Click · vision interpreter</li>
|
||||
<li>文 · 大语言模型</li>
|
||||
<li>图 · 生成式渲染</li>
|
||||
<li>感知 · 视觉解读</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-span-12 md:col-span-3 md:col-start-9">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-3">
|
||||
Colophon · III
|
||||
题 跋 · III
|
||||
</p>
|
||||
<p className="font-serif italic text-clay-700 text-base leading-relaxed">
|
||||
All three are configured separately — bring any OpenAI-compatible
|
||||
endpoint.
|
||||
三者各自独立配置 — 任何 OpenAI 兼容端点皆可。
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+12
-12
@@ -12,7 +12,7 @@ import type {
|
||||
StartResponse,
|
||||
StoryFrame,
|
||||
VisionResponse,
|
||||
} from "@dada/types";
|
||||
} from "@yume/types";
|
||||
|
||||
function PlayInner() {
|
||||
const router = useRouter();
|
||||
@@ -47,7 +47,7 @@ function PlayInner() {
|
||||
payload = { worldSetting: p.worldSetting, styleGuide: p.styleGuide };
|
||||
}
|
||||
} else if (params.get("custom") === "1") {
|
||||
const stored = sessionStorage.getItem("dada:custom");
|
||||
const stored = sessionStorage.getItem("yume:custom");
|
||||
if (stored) {
|
||||
try {
|
||||
payload = JSON.parse(stored);
|
||||
@@ -224,7 +224,7 @@ function PlayInner() {
|
||||
<div className="min-h-screen flex flex-col items-center justify-center px-8">
|
||||
<div className="max-w-md text-center animate-fade-in">
|
||||
<p className="text-[10px] smallcaps text-clay-500 mb-6">
|
||||
An · error · occurred
|
||||
出 · 了 · 点 · 状 · 况
|
||||
</p>
|
||||
<p className="font-serif italic text-clay-900 text-lg leading-[1.7] mb-10">
|
||||
{error}
|
||||
@@ -234,7 +234,7 @@ function PlayInner() {
|
||||
className="text-[10px] smallcaps text-clay-700 hover:text-ember-500 transition-colors inline-flex items-center gap-3"
|
||||
>
|
||||
<i className="fa-solid fa-arrow-left text-[9px]" />
|
||||
Return
|
||||
返 回
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -249,10 +249,10 @@ function PlayInner() {
|
||||
className="text-[10px] smallcaps text-clay-600 hover:text-clay-900 transition-colors flex items-center gap-2"
|
||||
>
|
||||
<i className="fa-solid fa-arrow-left text-[9px]" />
|
||||
Dada
|
||||
云梦
|
||||
</Link>
|
||||
<div className="flex items-center gap-3 text-[10px] smallcaps text-clay-500 num">
|
||||
<span>Frame · {String(turnNum).padStart(3, "0")}</span>
|
||||
<span>第 · {String(turnNum).padStart(3, "0")} · 帧</span>
|
||||
<span className="text-clay-300">·</span>
|
||||
<span className="hidden sm:inline truncate max-w-[180px]">
|
||||
{session?.id.slice(2, 14) ?? "—"}
|
||||
@@ -271,30 +271,30 @@ function PlayInner() {
|
||||
<div className="mt-7 md:mt-9 max-w-md w-full text-center min-h-[64px] flex items-center justify-center">
|
||||
{phase === "loading-first" && (
|
||||
<p className="text-[10px] smallcaps text-clay-500 animate-slow-pulse">
|
||||
Summoning · the · first · frame
|
||||
正 · 在 · 唤 · 起 · 第 · 一 · 帧
|
||||
</p>
|
||||
)}
|
||||
{phase === "interacting" && (
|
||||
<div className="flex flex-col items-center gap-2 animate-fade-in">
|
||||
<p className="text-[10px] smallcaps text-clay-500 animate-slow-pulse">
|
||||
AI · is · painting · the · next · moment
|
||||
AI · 正 · 在 · 描 · 画 · 下 · 一 · 刻
|
||||
</p>
|
||||
<p className="font-serif italic text-clay-400 text-xs">
|
||||
cached choices resolve in seconds · free-form takes longer
|
||||
预取选项秒级响应 · 自由点击稍候
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{phase === "ready" && intent?.targetLabel && (
|
||||
<p className="font-serif italic text-clay-500 text-base leading-relaxed animate-fade-in max-w-[320px]">
|
||||
<span className="text-[9px] smallcaps not-italic text-clay-400 mr-2 align-middle">
|
||||
Last · move ·
|
||||
上 · 一 · 步 ·
|
||||
</span>
|
||||
<span className="align-middle">{intent.targetLabel}</span>
|
||||
</p>
|
||||
)}
|
||||
{phase === "ready" && !intent && turnNum > 0 && (
|
||||
<p className="text-[10px] smallcaps text-clay-400 animate-fade-in">
|
||||
Click · anywhere · to · respond
|
||||
点 · 击 · 任 · 意 · 处 · 回 · 应
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -315,7 +315,7 @@ export default function PlayPage() {
|
||||
fallback={
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<span className="text-[10px] smallcaps text-clay-500 animate-slow-pulse">
|
||||
Loading
|
||||
载入中
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export function CustomForm() {
|
||||
if (!canSubmit) return;
|
||||
setSubmitting(true);
|
||||
sessionStorage.setItem(
|
||||
"dada:custom",
|
||||
"yume:custom",
|
||||
JSON.stringify({ worldSetting, styleGuide }),
|
||||
);
|
||||
router.push("/play?custom=1");
|
||||
@@ -64,7 +64,7 @@ export function CustomForm() {
|
||||
value={styleGuide}
|
||||
onChange={(e) => setStyleGuide(e.target.value)}
|
||||
rows={4}
|
||||
placeholder="例:Soft watercolor, warm afternoon light, anime visual novel style, classic dialogue panel⋯"
|
||||
placeholder="例:水彩柔光,午后暖意,动漫视觉小说画风,传统对话面板⋯"
|
||||
className="w-full bg-transparent border-0 border-b border-clay-900/20 px-0 py-3 text-clay-900 font-serif text-lg leading-[1.7] focus:outline-none focus:border-clay-700 transition-colors resize-none placeholder:font-serif placeholder:italic placeholder:text-base placeholder:leading-[1.7]"
|
||||
/>
|
||||
</div>
|
||||
@@ -72,17 +72,17 @@ export function CustomForm() {
|
||||
<div className="pt-6 flex items-center justify-between">
|
||||
<span className="text-[10px] smallcaps text-clay-500">
|
||||
{submitting
|
||||
? "Summoning the first frame…"
|
||||
? "正在唤起第一帧…"
|
||||
: canSubmit
|
||||
? "Ready when you are"
|
||||
: "Two paragraphs · enough to begin"}
|
||||
? "准 · 备 · 就 · 绪"
|
||||
: "两 · 段 · 即 · 可 · 开 · 场"}
|
||||
</span>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!canSubmit}
|
||||
className="group flex items-center gap-3 text-[10px] smallcaps text-clay-900 disabled:text-clay-300 disabled:cursor-not-allowed enabled:hover:text-ember-500 transition-colors duration-300"
|
||||
>
|
||||
Begin
|
||||
开 始
|
||||
<span className="w-10 h-px bg-current transition-all duration-300 group-enabled:group-hover:w-16" />
|
||||
<i className="fa-solid fa-arrow-right text-[9px]" />
|
||||
</button>
|
||||
|
||||
@@ -71,7 +71,7 @@ export function PlayCanvas({
|
||||
width: 30,
|
||||
height: 30,
|
||||
animation:
|
||||
"dada-ripple 1.6s cubic-bezier(0.16,1,0.3,1) infinite",
|
||||
"yume-ripple 1.6s cubic-bezier(0.16,1,0.3,1) infinite",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
@@ -100,7 +100,7 @@ export function PlayCanvas({
|
||||
>
|
||||
<div className="w-1.5 h-1.5 bg-clay-500 rounded-full animate-slow-pulse" />
|
||||
<p className="text-[9px] smallcaps text-clay-500 animate-slow-pulse">
|
||||
Painting · the · first · frame
|
||||
正 · 在 · 绘 · 制 · 第 · 一 · 帧
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -113,7 +113,7 @@ export function PlayCanvas({
|
||||
{dims ? `${dims.w} × ${dims.h} · png` : "—"}
|
||||
</span>
|
||||
<span className="text-[9px] smallcaps text-clay-400">
|
||||
{phase === "ready" ? "Tap · anywhere" : "···"}
|
||||
{phase === "ready" ? "任 · 意 · 点 · 击" : "···"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EngineConfig } from "@dada/types";
|
||||
import type { EngineConfig } from "@yume/types";
|
||||
|
||||
function readVar(name: string): string {
|
||||
const v = process.env[name];
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { NextConfig } from "next";
|
||||
const config: NextConfig = {
|
||||
reactStrictMode: true,
|
||||
typedRoutes: false,
|
||||
transpilePackages: ["@dada/engine", "@dada/ai-client", "@dada/types"],
|
||||
transpilePackages: ["@yume/engine", "@yume/ai-client", "@yume/types"],
|
||||
serverExternalPackages: ["sharp"],
|
||||
turbopack: {
|
||||
root: path.join(__dirname, "..", ".."),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@dada/web",
|
||||
"name": "@yume/web",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -11,9 +11,9 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dada/ai-client": "workspace:*",
|
||||
"@dada/engine": "workspace:*",
|
||||
"@dada/types": "workspace:*",
|
||||
"@yume/ai-client": "workspace:*",
|
||||
"@yume/engine": "workspace:*",
|
||||
"@yume/types": "workspace:*",
|
||||
"next": "^16.0.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
|
||||
Reference in New Issue
Block a user