Compare commits

...

44 Commits

Author SHA1 Message Date
john 2b344dfa60 fix(release): restart m.tkmind.cn portal tunnel after Portal deploy
Bundle memind-portal-tunnel.sh into the runtime artifact and kickstart
cn.tkmind.memind-portal-tunnel on 103 after Portal health checks so 105
nginx can reach 127.0.0.1:19081 following runtime releases.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 10:22:19 +08:00
john 12a1247c1f fix(mindspace): sync nested OA files and count workspace assets
Recursive workspace sync now imports files in oa/private/public subfolders,
references workspace paths without duplicating storage, and includes
workspace-sourced assets in category itemCount. Refresh counts when leaving
a category view.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 10:11:28 +08:00
john ea19ffb5fa feat: improve mindspace asset handling and local runtime paths 2026-06-28 12:18:26 +08:00
john 4a9bc710f1 feat: sync portal runtime fixes for release 2026-06-27 22:28:41 +08:00
john 8264e71f9e feat: release chat and mindspace UI updates 2026-06-27 21:57:21 +08:00
john c924b2bb77 docs: add release must-read checklist 2026-06-27 21:48:27 +08:00
john 0420c42fe2 fix: make schema bootstrap mysql safe 2026-06-27 21:40:58 +08:00
john fc5b50c936 fix: make goosed mcp paths container safe 2026-06-27 21:31:02 +08:00
john def9b0b5eb chore: Add backup files to .gitignore
- *.bak 备份文件不提交到版本控制
2026-06-27 08:25:34 +08:00
john da239bdf09 feat: Add imgproxy signer service
- imgproxy-signer.mjs: 图片代理签名服务
2026-06-27 08:25:27 +08:00
john 3bb5d21425 chore: Add runtime portal files and assets
- Portal 运行时文件和配置
- 测试资源和验证文件
- Plaza 封面图片资源
2026-06-27 08:25:18 +08:00
john a2374c3cd6 chore: Update configs and build files
- .gitignore 更新
- Caddyfile LB 配置更新
- WeChat MP 菜单脚本更新
- package-lock.json 更新
2026-06-27 08:25:11 +08:00
john 1798c07d42 docs: Update documentation and release rules
- 架构和规划文档更新
- 开发、工程、生产发布规则更新
- 服务隔离和升级指南
- README 更新
2026-06-27 08:25:06 +08:00
john 25f8223253 refactor: Business logic and dependencies updates
- 核心服务代码更新 (db, server, auth, proxy)
- Agent 相关模块更新 (mindspace, experience)
- 前端组件和 hooks 更新
- 数据库 schema 更新
- 依赖版本更新
2026-06-27 08:25:02 +08:00
john f1220a7905 feat: Goosed 本地 Docker 构建方案
- scripts/verify-goosed-docker.sh: 一键本地构建脚本
- docker-compose.local.yml: 本地开发环境
- docs/goosed-docker-local-verification.md: 本地测试指南
- docs/goosed-local-build-delivery.md: 构建交付说明
- docs/goosed-phase1-local-plan.md: 实施计划

完全本地化,无 CI 依赖,手工构建交付。
2026-06-27 08:24:57 +08:00
john 8627188ee7 feat: DesignSkillPanel — awesome-design-md 前台 UI 集成
- 新增 DesignSkillPanel 组件:54 品牌风格选择网格 + 任务描述输入
- ChatPanel 工具栏增加 design 按钮,点击弹出面板
- 生成结果回填到输入框,用户可编辑后发送
- 新增 API:listDesignStyles / invokeDesignSkill(走 /admin-api/skills/)
- .env.local: H5_DEV_ADMIN=http://127.0.0.1:8085(对接本地 memindadm)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 19:44:21 +08:00
john 8502775042 Fix UUID leaking as user display name in agent context
resolveUserAddressName now filters UUID-format strings (same as wx_*),
preventing user.id from being used as a display name when nickname/
displayName is absent.

buildSessionMemoryEntries always calls ensureUserMemoryProfile when
userContext is available so stale profiles with UUID display names are
auto-healed on next session init.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:56:22 +08:00
john 9b4a25799f Add smart ACK provider for WeChat MP replies
Replace fixed ackText with a rule-based AckProvider that picks
response templates by message type and intent (translate, summary,
rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync,
zero I/O, auto-falls back to config.ackText on any error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:19:03 +08:00
john 9ed4fd48d7 Fix sandbox MCP path resolution for session policy sync.
Resolve mindspace-sandbox-mcp.mjs from the code module location instead of h5Root, and copy it into the portal runtime artifact so goosed can spawn sandbox-fs on production.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 13:36:05 +08:00
john d51df2fb0a Hide goose from user-facing connection errors 2026-06-25 23:44:58 +08:00
john e133f9a3a4 Point gadm root to admin console 2026-06-20 16:11:57 +08:00
john daa5ab7199 Document gadm ops root routing 2026-06-20 16:09:03 +08:00
john 02c651a3d0 Unify current release docs and isolation notes 2026-06-20 15:54:19 +08:00
john db0149b025 Add release flow topology to deploy guide 2026-06-20 15:53:01 +08:00
john a0b684dba7 Add unified release topology to README 2026-06-20 15:52:04 +08:00
john fe4172d07e Add release entry overview to README 2026-06-20 15:47:41 +08:00
john 41470bafcb Unify plaza and gadm release docs 2026-06-20 15:46:32 +08:00
john cb51b94f2c Document gadm release flow 2026-06-20 15:41:22 +08:00
john 44e962e270 Document plaza 105-to-studio flow 2026-06-20 15:39:19 +08:00
john 2f07f3733e Add 105 rsync exclude rules 2026-06-20 15:18:59 +08:00
john 70492d9eba Add attachment text extraction, auto web news skill, and chat/voice UI updates.
Simplify asset upload temp paths, refresh deploy docs for Aliyun DNS topology, and ship MindSpace content-scan and auth improvements.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 15:08:10 +08:00
john 2e5afe3bfd feat: add fetch_news.py script to aggregate news from HN, Reddit, and GitHub
Co-authored-by: aider (deepseek/deepseek-chat) <aider@aider.chat>
2026-06-20 08:15:48 +08:00
john c4de6716f1 Restore Studio rsync exclude rules for safe production deploys.
Re-add the deploy exclude file and protect .tailscale so rsync --delete cannot remove production-only runtime data.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-19 23:09:22 +08:00
john 229805a070 Improve WeChat MP replies and ship MindSpace/H5 production updates.
Add WeChat service account routing with sync acks, connectivity tests, and context isolation; document deploy runbooks; and bundle related MindSpace, voice, Plaza, and server gateway changes for production rollout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-19 23:06:43 +08:00
Your Name b0f5d6a51c Extract memind_adm admin server, add local dev tooling, and remove image-generation.
Split platform admin and ops APIs into standalone admin-server.mjs with network guards; simplify billing to RMB token pricing, refactor user auth, and add rsync deploy plus local-test scripts and docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 16:39:39 -07:00
John ab0718938e Fix OA workspace cover thumbnails and add space chat new session.
Resolve mindspace-cover images from workspace directories when generating feed thumbnails, refresh stale SVGs missing embedded photos, and disable thumbnail API caching so fixes take effect immediately. Also add a new session control to the space chat panel, including on mobile.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 17:57:00 -07:00
John 6d99d762da Add image-designer skill, align billing to DeepSeek ×1, and enrich Plaza demo.
Introduce AI image generation with chat shortcut and agent API, improve MindSpace chat-to-page save resolution, and seed Plaza covers with production deploy scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:29:19 -07:00
John 03690ee354 Fix duplicate session billing and align pricing with DeepSeek ×3.
Serialize billSessionUsage with row locks, expose rates on recharge, add compensation script and admin usage views.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 04:45:15 -07:00
john befeedfd37 Remove embedded admin UI and redirect admins to standalone ops app.
Extract admin routes from the main SPA, add plaza-api bootstrap module, and track ops pnpm lockfile.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 19:43:56 +08:00
john f818dd0307 Add WeChat in-app JSAPI recharge for g2.tkmind.cn.
Use JSAPI with bound openid inside WeChat instead of QR long-press, and include related auth redirect and admin UX fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:20:04 +08:00
John bb70634a96 Remove recent billing list from balance popover.
Keep the popover focused on balance summary and token usage without fetching usage records on open.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 01:03:35 -07:00
John 79457230c1 Improve MindSpace visual editor UX and default RMB billing.
Add color-coded edit highlights with an in-preview legend, strip CSP meta
for srcdoc editing, and simplify fullscreen preview to immersive visual edit
only. Default billing to CNY token rates unless H5_USE_BACKEND_COST=1.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 00:59:28 -07:00
john 8d2f55771c Fix MindSpace preview crash and simplify balance ring popover.
Wrap preview mode in ChatProvider so useChat works, and drop recharge ledger from the balance dropdown to keep it compact.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 15:55:20 +08:00
John d376161ab0 docs: publish v0.1.0-baseline for team development
Announce the v0.1.0-baseline tag (25d9c8c) as the starting point for all
future branches and document checkout workflow in docs/BASELINE.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 23:46:26 -07:00
552 changed files with 76666 additions and 4717 deletions
+43 -32
View File
@@ -1,28 +1,38 @@
# TKMind H5 环境变量(复制为 .env 后按需修改)
#
# 本地开发(默认只做本地,不自动发布生产):
# 1. pnpm dev # 热更新 (http://127.0.0.1:5173)
# 2. pnpm run test:local # 生产构建本地跑 (http://127.0.0.1:8081)
# 3. pnpm run test:fruit-john-e2e # john 水果主题:预览图 + 可点击链接 + 我的空间
# 4. node scripts/mindspace-rebuild-thumbnails.mjs # 批量重建预览图(可选)
#
# 发布生产:仅当明确要求「发布生产」时再执行:
# pnpm run deploy:105 或 pnpm run deploy:prod 或 ./rsync_to_server.sh
# 105 配置见 deploy/h5-105.env.example
# 本地开发(127.0.0.1 + 端口,见 docs/local-dev.md
# pnpm dev
# MindSpace: http://127.0.0.1:5173/?preview=mindspace
#
# 后端代理(server.mjs / vite dev proxy 共用)
TKMIND_API_TARGET=https://127.0.0.1:18006
TKMIND_SERVER__SECRET_KEY=local-dev-secret
H5_PORT=8081
# Agent 生成链接用(本地开发建议 8081;生产再改为 https://goo.tkmind.cn
H5_PUBLIC_BASE_URL=http://127.0.0.1:8081
# MindSpace 与 Plaza 跨子域共享登录(如 g2.tkmind.cn + plaza.tkmind.cn
# H5_COOKIE_DOMAIN=.tkmind.cn
H5_PUBLIC_BASE_URL=http://127.0.0.1:5173
# ===== memind_adm(独立后台服务)=====
# 平台超管 /admin-api/* 与广场运营 /api/ops/v1/* 已从公网服务拆出,独立进程运行。
# 登录仍在主域完成;后台凭 H5_COOKIE_DOMAIN=.tkmind.cn 共享的会话 Cookie 鉴权(生产务必设置)。
ADMIN_PORT=8082
ADMIN_HOST=127.0.0.1
ADMIN_PUBLIC_HOST=gadm.tkmind.cn
# 本进程挂载哪些控制台(可拆分架构):admin=平台超管, ops=广场运营。
# 默认两者合一;将来拆成两个进程时,A 实例设 admin、B 实例设 ops,路由代码无需改动。
# ADMIN_CONSOLES=admin,ops
# 每控制台独立网络护栏(逗号分隔;留空=放开。支持精确 IP 与 CIDR)。
# 超管面建议收得最紧(仅内网/VPN),广场运营可放宽给审核团队网段。
# ADMIN_API_ALLOWED_HOSTS=gadm.tkmind.cn
# ADMIN_API_IP_ALLOWLIST=10.0.0.0/8,127.0.0.1
# OPS_API_ALLOWED_HOSTS=gadm.tkmind.cn
# OPS_API_IP_ALLOWLIST=
# 多用户系统(MySQL 配置后启用;未配置时回退到 H5_ACCESS_PASSWORD
DATABASE_URL=mysql://boot:password@localhost:3306/tkmind
# 或分别设置 MYSQL_HOST / MYSQL_PORT / MYSQL_USER / MYSQL_PASSWORD / MYSQL_DATABASE
H5_USERS_ROOT=/root/tkmind_go/users
# 新用户赠送余额(人民币分,500 = ¥5.00;勿与美元 cents 混淆)
H5_SIGNUP_BALANCE_CENTS=500
H5_ADMIN_USERNAME=admin
H5_ADMIN_PASSWORD=change-me-admin
@@ -31,28 +41,30 @@ H5_ADMIN_PASSWORD=change-me-admin
# LLM Key 数据库加密(可选;默认派生自 TKMIND_SERVER__SECRET_KEY
# H5_SETTINGS_ENCRYPTION_KEY=change-me-encryption-key
# 启动时自动导入 Relay(若不存在同名配置)
# H5_RELAY_BOOTSTRAP_NAME=Relay Buyer Ollama
# H5_RELAY_BOOTSTRAP_NAME=Local Goose Relay DeepSeek
# H5_RELAY_BOOTSTRAP_URL=http://127.0.0.1:18300/relay/buyer/v1/chat/completions
# H5_RELAY_BOOTSTRAP_API_KEY=your-bearer-token
# H5_RELAY_BOOTSTRAP_MODEL=qwen2.5:3b
# H5_RELAY_BOOTSTRAP_MODELS=qwen2.5:3b,llama3.2:1b
# H5_RELAY_BOOTSTRAP_PROVIDER=ollama
# H5_RELAY_BOOTSTRAP_MODEL=deepseek-chat
# H5_RELAY_BOOTSTRAP_MODELS=deepseek-chat,deepseek-reasoner
# H5_RELAY_BOOTSTRAP_PROVIDER=deepseek
# 一键对齐本地 goosed + Goose Desktop relaynode scripts/fix-local-goose-relay.mjs
# 本地 Ollama fallbackDeepSeek 额度不足,或 andu Relay 500agent 请求体含 tools 超过 ~8.5KB)时自动切换
# Local Ollama fallback — creditsExhausted or relay 500 (nginx body limit with tool payloads).
# H5_LOCAL_LLM_FALLBACK=0
# H5_LOCAL_LLM_URL=http://127.0.0.1:11434/v1/chat/completions
# H5_LOCAL_LLM_MODEL=qwen2.5-coder:7b
# H5_LOCAL_LLM_MODEL=qwen2.5:3b
# H5_LOCAL_LLM_API_KEY=ollama
# H5_LOCAL_LLM_NAME=Local Ollama 7B
H5_ACCESS_PASSWORD=change-me
# 计费(Phase 2
# H5_USE_BACKEND_COST=1 # 优先用后端 accumulatedCostUSD)计费
# H5_USD_CNY_RATE=7.2
# H5_BILL_INPUT_CENTS_PER_1K=2
# H5_BILL_OUTPUT_CENTS_PER_1K=6
# 计费(Phase 2,金额单位均为人民币分
# 默认按 Token 单价扣费(人民币结算);勿开启美元成本换算除非明确需要
# H5_USE_BACKEND_COST=0
# H5_BILL_INPUT_CENTS_PER_1K=2 # 输入 Token2 分/1k(¥0.02/1k
# H5_BILL_OUTPUT_CENTS_PER_1K=6 # 输出 Token6 分/1k(¥0.06/1k
# H5_MIN_BILL_CENTS=1
# 仅调试:H5_USE_BACKEND_COST=1 + H5_USD_CNY_RATE=7.2(上游 USD × 汇率 → 人民币分)
# 用户自助充值(微信支付)
# H5_RECHARGE_TIERS_CENTS=500,1000,3000,5000,10000,20000
@@ -81,6 +93,10 @@ H5_ACCESS_PASSWORD=change-me
# H5_WECHAT_PLATFORM_CERT="-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
#
# H5_WECHAT_NOTIFY_URL=https://goo.tkmind.cn/webhooks/wechat-pay/notify
# 微信内 JSAPI 支付(服务号网页):
# - 服务号「设置 → 功能设置 → JS接口安全域名」:m.tkmind.cn
# - 商户平台「产品中心 → 开发配置 → 支付授权目录」:https://m.tkmind.cn/
# - 用户须先用同一服务号微信 OAuth 登录(获取 openid)后再充值
# 本地调试验签可临时开启(生产务必关闭):
# H5_WECHAT_SKIP_NOTIFY_VERIFY=0
@@ -120,22 +136,17 @@ VITE_TKMIND_WORKING_DIR=/Users/john/PycharmProjects/tkmind
# Plaza 发现广场(本机为主,105 已停用)
# PLAZA_AUTO_APPROVE=true
# 文档:docs/plaza-local.md
# 首次:sudo pnpm setup:plaza-dns # 仅纯本地 HTTPS 时需要;走 Tunnel 请用 setup:plaza-dns:remove
# 日常:pnpm dev:plaza | 浏览器:pnpm open:plaza | 诊断:pnpm check:plaza
# 公网 plaza.tkmind.cn 经 Cloudflare Tunnel → 本机 :3001(需 dev:plaza 常驻)
# PLAZA_LOCAL_HOST=plaza.tkmind.cn
# PLAZA_PUBLIC_BASE=https://plaza.tkmind.cn
# VITE_PLAZA_BASE=https://plaza.tkmind.cn
# CLOUDFLARE_TUNNEL_CONFIG=/Users/john/Project/ollama/cloudflare/config.yml
# CLOUDFLARE_TUNNEL_NAME=ollama-tkmind
# VITE_PLAZA_BASE=http://127.0.0.1:3001
# 文档:docs/plaza-local.md | 本地:http://127.0.0.1:3001/plaza
# MindSpace(默认启用;子功能需按需开启)
# MINDSPACE_ENABLED=false
# MINDSPACE_UPLOAD_ENABLED=false
# MINDSPACE_PUBLISH_ENABLED=true
# MINDSPACE_PRIVATE_ENABLED=false
# MINDSPACE_MAX_FILE_BYTES=5242880
# Agent 后台任务(创建/执行空间内 Agent 任务,默认关闭)
# MINDSPACE_AGENT_JOBS_ENABLED=true
# MINDSPACE_INTERNAL_AGENT_SECRET=local-dev-secret
# MINDSPACE_FREE_PUBLIC_PAGE_LIMIT=10
# MINDSPACE_STORAGE_ROOT=/path/to/mindspace-storage
+4
View File
@@ -6,6 +6,7 @@ ops/dist/
.env
.env.local
.env.*.local
scripts/g2-aliyun-cert.env
*.log
*.pid
@@ -18,3 +19,6 @@ users/
.DS_Store
.idea/
.vscode/
.aider*
.env.experience-test
*.bak
+25
View File
@@ -0,0 +1,25 @@
Portal runtime artifact
This directory is meant to run on production without the source tree.
Required persisted items to inherit on the host:
.env
MindSpace/
data/
users/
.tailscale/
public/plaza-covers/
logs/
Bundled alongside server.mjs (required for sandbox-fs MCP):
mindspace-sandbox-mcp.mjs (esbuild bundle; includes schedule-service deps)
Key runtime differences must stay in .env, not in the artifact:
DATABASE_URL / MYSQL_*
H5_PUBLIC_BASE_URL
TKMIND_API_TARGET / TKMIND_API_TARGET_1
H5_USERS_ROOT / MINDSPACE_STORAGE_ROOT / MEMIND_SHARED_PUBLISH_ROOT
Deployment and operations transport:
105 fixed IP: 120.26.184.105
103 / Studio fixed IP: 58.38.22.103
Do not switch back to 10.10.* LAN paths unless explicitly required.
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
{
"name": "tkmind-h5-portal-runtime",
"private": true,
"type": "module"
}
@@ -0,0 +1 @@
nXjhx0ErC6MhQ0SZ
+159
View File
@@ -0,0 +1,159 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="John 的专属欢迎页面 - TKMind 为您呈现">
<meta name="mindspace-cover" content='{"tag":"报告","emoji":"👋","accent":"#f093fb","accent2":"#24243e","subtitle":"Hello John","cover":"https://images.unsplash.com/photo-1579547945413-497e1b99dac0?w=1200&q=80"}'>
<title>Hello, John!</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
overflow: hidden;
}
/* 动态粒子背景 */
.bg-particles {
position: fixed;
inset: 0;
z-index: 0;
overflow: hidden;
}
.bg-particles span {
position: absolute;
width: 6px;
height: 6px;
background: rgba(255, 255, 255, 0.15);
border-radius: 50%;
animation: float 20s infinite;
}
.bg-particles span:nth-child(1) { top: 10%; left: 10%; animation-duration: 18s; animation-delay: 0s; }
.bg-particles span:nth-child(2) { top: 30%; left: 80%; width: 10px; height: 10px; animation-duration: 22s; animation-delay: 2s; }
.bg-particles span:nth-child(3) { top: 70%; left: 20%; animation-duration: 16s; animation-delay: 4s; }
.bg-particles span:nth-child(4) { top: 85%; left: 85%; width: 8px; height: 8px; animation-duration: 24s; animation-delay: 1s; }
.bg-particles span:nth-child(5) { top: 50%; left: 50%; width: 4px; height: 4px; animation-duration: 20s; animation-delay: 3s; }
.bg-particles span:nth-child(6) { top: 15%; left: 60%; animation-duration: 19s; animation-delay: 5s; }
.bg-particles span:nth-child(7) { top: 60%; left: 5%; width: 7px; height: 7px; animation-duration: 21s; animation-delay: 0.5s; }
.bg-particles span:nth-child(8) { top: 40%; left: 70%; width: 5px; height: 5px; animation-duration: 17s; animation-delay: 2.5s; }
@keyframes float {
0% { transform: translateY(0) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(-100vh) rotate(720deg); opacity: 0; }
}
.card {
position: relative;
z-index: 1;
text-align: center;
padding: 60px 80px;
background: rgba(255, 255, 255, 0.05);
border-radius: 24px;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow:
0 25px 50px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
animation: fadeIn 1.2s ease-out;
}
h1 {
font-size: 72px;
font-weight: 700;
background: linear-gradient(135deg, #f093fb, #f5576c, #4facfe);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 16px;
animation: pulse 3s ease-in-out infinite;
letter-spacing: 4px;
}
p {
font-size: 24px;
color: rgba(255, 255, 255, 0.7);
letter-spacing: 2px;
}
.emoji {
font-size: 48px;
display: block;
margin-bottom: 24px;
animation: wave 2s ease-in-out infinite;
}
.footer {
margin-top: 36px;
font-size: 13px;
color: rgba(255, 255, 255, 0.3);
letter-spacing: 1px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.03); }
}
@keyframes wave {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(15deg); }
75% { transform: rotate(-15deg); }
}
@media (max-width: 600px) {
.card {
padding: 40px 32px;
margin: 20px;
border-radius: 16px;
}
h1 {
font-size: 48px;
}
p {
font-size: 18px;
}
.emoji {
font-size: 36px;
}
}
</style>
</head>
<body>
<div class="bg-particles">
<span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span>
</div>
<div class="card">
<span class="emoji">👋</span>
<h1>Hello!</h1>
<p>Welcome, John</p>
<div class="footer">powered by TKMind</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Some files were not shown because too many files have changed in this diff Show More