# Lemonadeccc - Full Content > A frontend learning library with posts on AI, development. --- ## AI Workflow Summary - URL: https://blog.lemonadec.cc/posts/new-ai-tools-for-me - Date: 2026-03-01 - Language: en - Type: Article This post is not a tool list. It is the workflow I distilled after repeated iteration in real projects. The process is straightforward: define constraints first, execute in parallel with multiple models, then converge with a unified review gate. ## 1. Design Stage In the design stage, I align information architecture and produce an iteratable first draft as quickly as possible. ### 1) Wireframe Sketches - [wiretext](https://wiretext.app/): Quickly turns page structure into wireframes, useful for confirming information hierarchy first. - [mockdown](https://www.mockdown.design/): Expresses page block layout in text, useful for early discussion and requirement clarification. ### 2) UI Shell and Variants - [Pencil](https://www.pencil.dev/): Generates editable UI drafts through prompts. - [variant ai](https://www.variant.ai/): Start from a close style, refine with prompts, then export `.js` and continue structural refinement with Claude Code or Codex. ## 2. Development Stage ### 1) Baseline: Multi-Agent + Git Worktree My current approach for simpler requirements: 1. Split one requirement into 2-4 relatively independent subtasks. 2. Bind each subtask to an isolated worktree and session. 3. Merge small verifiable increments first, then converge cross-module changes. This significantly reduces context pollution and task interference. There is a boundary, though: when task coupling is high, over-splitting worktrees can increase integration cost. ### 2) Third-Party Tooling Landscape I used to rely on: - [superset](https://github.com/superset-sh/superset): a parallel worktree orchestration tool. - [happy](https://github.com/slopus/happy): remote control for Claude Code. Now that Claude officially covers multi-worktree workflows and part of remote capabilities, these tools are better used as optional CLI enhancers. ## 3. CCG Workflow: Turning Multi-Model Collaboration into Process In my stack, `ccg-workflow` acts as the orchestration layer: Claude Code coordinates, frontend tasks are routed to Gemini first, backend tasks to Codex first, then Claude performs unified review and lands patches. ### 1) Installation and Prerequisites ```bash npx ccg-workflow ``` - Requires `Node.js 20+`. - Optionally install `Codex CLI` (backend-focused) and `Gemini CLI` (frontend-focused). ### 2) Common Commands - Full workflow: `/ccg:workflow` - Planning + execution split: `/ccg:plan` + `/ccg:execute` - Task-oriented: `/ccg:frontend`, `/ccg:backend`, `/ccg:debug`, `/ccg:optimize`, `/ccg:review` Plan first, then execute: ```bash /ccg:plan 实现用户认证功能 /ccg:execute .claude/plan/user-auth.md ``` This pattern reduces context loss from session switching and minimizes goal drift during implementation. ### 3) Built-in CCG Capabilities - Spec-driven (`/ccg:spec-*`): - Suitable for complex requirements with many constraints and high drift risk. - Value: it compresses "free generation" into "constraint-driven execution". - Parallel implementation (`/ccg:team-*`): - Suitable for tasks that can be split into 3+ independent modules. - Value: reduces context cross-talk via `/clear` + file-state passing. ### 4) Configuration and Pitfalls - Tune timeout parameters in `~/.claude/settings.json` (such as `CODEX_TIMEOUT`, `BASH_DEFAULT_TIMEOUT_MS`). - Choose MCP tools by complexity: ContextWeaver + Context7 / Playwright / DeepWiki / Exa. ## 4. Skills as Reusable Process Common skills resources: - [skills official](https://skills.sh/) - [superpowers](https://github.com/obra/superpowers) - [claude-mem](https://github.com/thedotmack/claude-mem/tree/main) - [react-best-practices](https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices) How I use them: - `superpowers`: process orchestration (automatic planning, staged execution, completion checks). - `claude-mem`: context compression and memory management (useful for long-running workflows). - `react-best-practices`: performance and code quality constraints during implementation. ## 5. MCP Capability Expansion I currently use Lighthouse MCP primarily: - `@danielsogl/lighthouse-mcp`: full-featured, with support for Core Web Vitals, budgets, and more. Two recurring pitfalls: 1. When running Lighthouse, explicitly ask the LLM to test both desktop and mobile. Otherwise, many automated flows run mobile-only. 2. Automated scores can differ from manual DevTools runs. Use trends and bottleneck localization as the main signal, not a single absolute score. If your site is hosted on Cloudflare and crawler/audit access fails, check `robots.txt` and caching policy first, then purge `robots.txt`-related cache if needed. ## 6. Testing and Review Pipeline ### 1) Explicitly Require Three Test Layers in Prompt After implementation, I use this reusable instruction: ```text 请基于当前变更补齐并执行测试,要求: 1) 单元测试(unit tests):覆盖核心函数、边界条件、异常路径。 2) 集成测试(integration tests):覆盖模块间协作、数据流与接口契约。 3) 端到端测试(e2e tests):覆盖关键用户路径(成功流 + 失败流)。 执行要求: - 先写测试再修复实现,直到全部通过。 - 输出每类测试的新增用例清单、执行命令和结果摘要。 - 标注当前未覆盖风险点和建议补测项。 ``` ### 2) Cross-Model Code Review After tests pass, I run review with different models and focus on: 1. Potential bugs and boundary failures. 2. Readability and maintainability. 3. Performance, complexity, and scalability risks. 4. Whether test coverage matches business risk. The key gain of multi-model review is reducing single-model blind spots. ### 3) Human Review After AI review, I run a manual review pass to verify: 1. The requirement is truly closed-loop, not just textually satisfied. 2. No obvious regression risk is introduced. 3. Naming, boundary handling, and error handling align with team conventions. 4. Tests cover the highest-risk paths. The role of human review is not to repeat AI output; it is to provide business-context judgment and final risk containment. ### 4) GitHub App Auto Review After CI After PR submission and CI pass, I run another automated review round with GitHub Apps, usually including: - [Coderabbit](https://coderabbit.ai/) - [Gemini Code Assist](https://codeassist.google/) - [qodo](https://www.qodo.ai/) I am also vibe-building a testing-focused [pr-agent](https://github.com/condevtools/pr-agent) to automatically summarize "test results + risk points + review suggestions" into PRs/Issues and improve review decisions. ## 7. Current Reusable End-to-End Workflow 1. Use wireframe tools to define information hierarchy and page structure. 2. Use UI generation tools to get an editable first draft quickly. 3. Prioritize MVP in development, then parallelize independent subtasks through worktrees. 4. For complex requirements, lock constraints with `/ccg:plan` or `/ccg:spec-*` before implementation. 5. Before merge, run unified review (`/ccg:review` + manual spot checks), then do stabilization refactoring (robustness, maintainability, edge handling). The core benefit of this workflow: high early velocity, stable mid-stage quality, and lower long-term maintenance cost. --- ## Build an Image Hosting Setup with Cloudflare R2 + PicGo - URL: https://blog.lemonadec.cc/posts/cloudflare-r2-imgbed - Date: 2026-02-26 - Language: en - Type: Article Cloudflare R2's free plan includes 10GB per month, which is usually enough for a personal image host. ![free-tier](https://imgbed.lemonadec.cc/2026/02/blog-cloudflare-r2-imgbed-free-tier.png) ### 1. Create an R2 Bucket 1. Open the Cloudflare dashboard and go to `R2 -> Create bucket`. 2. Enter a bucket name and create it. 3. Open the bucket, then go to `Settings -> Add custom domain` and enter your domain. 4. Confirm the setup, and the corresponding DNS record will be generated. 5. Upload one file manually first to confirm the bucket can read and write normally. ### 2. Create an API Token Path: `R2 -> Account Details -> Manage API Tokens -> Create token` 1. Set token permission to `Object Read & Write`. 2. Set scope to `Apply to specific bucket only`. 3. After creation, save the following: - `Access Key ID` - `Secret Access Key` ### 3. PicGo Setup 1. Download and install [PicGo](https://github.com/Molunerfinn/PicGo). 2. Install the `S3` plugin from the PicGo plugin marketplace. 3. Open `PicGo -> Image Hosting Settings -> Amazon S3` and create a new config. Parameter mapping: | PicGo Field | Value | | --- | --- | | Access Key ID | R2 `Access Key ID` | | Secret Access Key | R2 `Secret Access Key` | | Bucket | Your bucket name shown in R2 | | File Path | `{year}/{month}/{fileName}.{extName}` | | Custom Endpoint | The S3 endpoint provided on the R2 page | | Reject Unauthorized TLS | `yes` | | ACL | `public-read` | ### 4. Upload Verification 1. Select an image in PicGo and upload it. 2. Confirm the file appears in the corresponding Cloudflare R2 bucket. 3. Copy the uploaded link in PicGo and open it to test access. --- ## Cloudflare Tunnel + Zero Trust Stable SSH Access for Netcup VPS - URL: https://blog.lemonadec.cc/posts/cloudflare-tunnel-de-vps - Date: 2026-02-25 - Language: en - Type: Article When I checked my OpenClaw service, it stopped replying on Feishu, so I started investigating the server. It turned out the issue was not a crashed `sshd`, but an unstable cross-border route (Germany to China Unicom). The final solution was to deploy `cloudflared` on the server, map `ssh-de.condevtools.com` to `localhost:22` through a Tunnel, and connect locally with `cloudflared access ssh`. This removes direct dependence on port `22` exposure and gives better stability and control. ### Current Status Check The provider's VNC was accessible, SSH service was active, port `22` was listening, and logs contained `Connection reset by peer [preauth]`. ```bash systemctl status ssh ss -tlnp | grep sshd ufw status # 或 iptables -S / nft list ruleset journalctl -u ssh -n 100 --no-pager ``` Key checks: - `systemctl status ssh`: verify whether SSH service is running. - `Active: active (running)`: service started normally. - `inactive/failed`: service is down; fix service issues first (config, key files, startup failure, etc.). - `ss -tlnp | grep sshd`: verify whether SSH is listening on a port. - `0.0.0.0:22` and `[::]:22`: listening on all IPv4/IPv6 addresses. - Only `127.0.0.1:22`: listening locally only; external access will fail. - No output: not listening (service not running or port changed). - `ufw status`: check whether system firewall blocks SSH. - `Status: inactive`: no system-level firewall block. - `active` without `22/tcp ALLOW` (or your custom SSH port) will block access. - `journalctl -u ssh -n 100 --no-pager`: inspect authentication and connection logs. - `Accepted publickey`: login succeeded. - `Failed password`: credential issue. - `Connection reset by peer [preauth]`: connection reached the server, but was reset before authentication, commonly caused by network path issues. Conclusion: service OK + port OK + UFW not blocking + `preauth reset` in logs points to a network path issue rather than broken SSH server configuration. ### Solutions #### 1. Use a Hong Kong VPS as an SSH jump host First SSH to a Hong Kong VPS, then SSH to the Germany VPS, or host a WebSSH endpoint on the Hong Kong VPS. Note: public WebSSH services are unsafe and may leak credentials or increase attack surface. ```sshconfig # ~/.ssh/config Host hk HostName HongKongIP User your_user Port 22 IdentityFile ~/.ssh/id_rsa Host de-via-hk HostName GermanyIP User your_user Port 22 ProxyJump hk IdentityFile ~/.ssh/id_rsa ``` ```bash ssh de-via-hk ``` ![sshx](https://imgbed.lemonadec.cc/2026/02/sshx.png) You can also refer to this guide: [Use a low-cost Hong Kong VPS as a relay](https://www.vircs.com/blogs/52). I kept searching for other options due to cost. #### 2. Use `sshx` as a temporary web terminal You can install and run [sshx](https://github.com/ekzhang/sshx) on the server via VNC, then open the generated link in a local browser. ```bash curl -sSf https://sshx.io/get | sh sshx ``` This works for emergency access, but can be unstable and requires reopening VNC to restart `sshx`, so I later switched to Cloudflare Tunnel. #### 3. Cloudflare Tunnel and cloudflared Cloudflare Tunnel is a reverse tunnel initiated by the origin: after `cloudflared` runs on the server, it actively connects to Cloudflare edge and forwards traffic for a specific domain (such as `ssh-de.condevtools.com`) to a local service (such as `localhost:22`). It mainly solves three problems: - unstable cross-border direct routes - ports affected by ISP or network policy - security risks of exposing SSH on the public internet The workflow can be summarized as "outbound tunnel + edge authentication + origin forwarding": users first reach Cloudflare edge, pass Zero Trust Access checks, and then enter the established tunnel to the origin. So even if you close public SSH exposure on the server, you still keep a stable and safer remote ops channel. `Cloudflare Tunnel` is the service itself, while `cloudflared` is the official client: the former defines capability, the latter creates tunnels, initiates access, and forwards traffic. ### Server Side #### 1. Install cloudflared (Ubuntu 24.04) ```bash sudo apt-get update sudo apt-get install -y cloudflared cloudflared --version ``` #### 2. Log in to Cloudflare and generate `/root/.cloudflared/cert.pem` ```bash cloudflared tunnel login ls -l /root/.cloudflared/cert.pem ``` #### 3. Create a Tunnel and bind an SSH subdomain ```bash cloudflared tunnel create de-ssh cloudflared tunnel list cloudflared tunnel route dns de-ssh ssh-de.condevtools.com ``` #### 4. Generate configuration ```bash TUNNEL_ID=$(cloudflared tunnel list | awk '$2=="de-ssh"{print $1}') cat >/root/.cloudflared/config.yml < Access -> Applications -> Add application -> Self-hosted` 2. Set `Domain` to `ssh-de.condevtools.com` 3. Set `Policy` to only allow your own account/email, and enable MFA ### Local Mac #### 1. Install client ```bash brew install cloudflared cloudflared --version ``` #### 2. Direct connection test ```bash ssh -o "ProxyCommand=$(which cloudflared) access ssh --hostname %h" root@ssh-de.condevtools.com ``` #### 3. Optional: write to `~/.ssh/config`, then use `ssh de-cf` ```sshconfig Host de-cf HostName ssh-de.condevtools.com User root ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h ``` ```bash ssh de-cf ``` --- ## openclaw + Feishu Deployment Guide - URL: https://blog.lemonadec.cc/posts/openclaw-feishu - Date: 2026-02-21 - Language: en - Type: Article - zsh: https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH - oh-my-zsh: https://ohmyz.sh/ - System update: apt update - System upgrade: apt upgrade - openclaw install: https://docs.openclaw.ai/zh-CN/install - Feishu: https://docs.openclaw.ai/zh-CN/channels/feishu - Create app: https://open.feishu.cn/app - Enable bot capability - Add permissions in bulk - Install plugin: https://github.com/m1heng/Clawdbot-feishu - openclaw plugins install @m1heng-clawd/feishu - Configure channel: https://docs.openclaw.ai/zh-CN/channels/feishu - openclaw channels add - openclaw gateway restart - App settings (developer console): - Event subscriptions (Events and callbacks): subscribe via long connection - Add event: im.message.receive_v1 - Workspace (mobile / Feature menu - Messages - Workspace) - You may need to verify the pairing code: openclaw pairing approve feishu pairing_code - VPS: - [Netcup](https://www.netcup.com/en/) --- ## Building a Temporary Mail Service with Cloudflare - URL: https://blog.lemonadec.cc/posts/cloudflare-temporary-mail - Date: 2026-02-20 - Language: en - Type: Article Many platforms require email verification. Regular mailbox prefixes are fixed, which makes testing, traffic splitting, or temporary signups for certain sites inconvenient. - Open-source project: https://github.com/dreamhunter2333/cloudflare_temp_email - Official docs: https://temp-mail-docs.awsl.uk ### Architecture This temporary mail setup has 4 core parts: 1. `Worker`: handles incoming mail logic, mailbox generation, and backend APIs 2. `D1`: stores emails and address data 3. `KV`: stores session and short-lived state 4. `Email Routing + custom domain`: routes mail sent to `*@your-domain` into the Worker ### Prerequisites 1. A domain already hosted on Cloudflare (for example, `mail.domain.com`) 2. A Cloudflare account with Workers / D1 / Email Routing permissions 3. Prepare a usable subdomain dedicated to temporary mail 4. It is recommended to plan two subdomains in advance: - Backend Worker: `api.domain.com` - Frontend Pages: `mail.domain.com` ### 1. Create the D1 Database in Cloudflare Path: `Workers & Pages -> D1 SQL Database -> Create` 1. Set the database name to `temp-mail` (or your own name) 2. Open the database details page after creation 3. Open `Console` or `Query` 4. Copy and execute [docs/schema.sql](https://github.com/dreamhunter2333/cloudflare_temp_email/blob/main/db/schema.sql) from the project At this point, database initialization is done. ### 2. Deploy the Backend Mail Service #### 1) Create a new Worker Path: `Compute (Workers) -> Workers & Pages -> Create -> Worker -> Create Worker` 1. Create a new Worker 2. Name it and click `Deploy` #### 2) Set compatibility flags Path: `Workers & Pages -> Worker -> Settings -> Runtime` 1. Add `nodejs_compat` manually under `Compatibility flags` 2. Set `Compatibility date` to no earlier than `2024-09-23` #### 3) Upload backend `worker.js` and deploy 1. Download backend file: https://github.com/dreamhunter2333/cloudflare_temp_email/releases/latest/download/worker.js 2. Go to: `Workers & Pages -> Worker -> Overview -> Edit Code` 3. Remove the default file 4. Click `Explorer` on the left, right-click in the file list area -> `Upload`, then upload `worker.js` 5. Click `Deploy` in the top-right corner #### 4) Add variables one by one in Variables and Secrets Path: `Workers & Pages -> Worker -> Settings -> Variables and Secrets` Configure them one by one. Start with this minimal runnable set (recommended): | Variable | Type | Example | Description | | --- | --- | --- | --- | | `DOMAINS` | JSON | `["api.domain.com"]` | Available domain list, supports multiple domains | | `JWT_SECRET` | Text | `your_jwt_secret` | JWT secret, replace with a strong random string | | `ADMIN_PASSWORDS` | JSON | `["your_password"]` | Admin password list, configure at least one | | `ENABLE_USER_CREATE_EMAIL` | Text | `true` | Allow users to create addresses | | `ENABLE_USER_DELETE_EMAIL` | Text | `true` | Allow users to delete emails | | `ENABLE_ADDRESS_PASSWORD` | Text | `true` | Enable password login for mailbox addresses | Common extended variables (optional): | Variable | Type | Example | Description | | --- | --- | --- | --- | | `ADMIN_USER_ROLE` | Text | `admin` | Admin role name | | `NO_LIMIT_SEND_ROLE` | Text | `admin` | Role with unlimited sending | | `ENABLE_AUTO_REPLY` | Text | `false` | Auto-reply switch | | `DEFAULT_DOMAINS` | JSON | `["api.domain.com"]` | Default domains available to unauthenticated users | | `USER_ROLES` | JSON | See example below | Custom roles and domain permissions | Copyable variable value examples (to avoid format errors): ```text DOMAINS=["api.domain.com"] ADMIN_PASSWORDS=["your_password","your_password_two"] DEFAULT_DOMAINS=["api.domain.com"] USER_ROLES=[ {"domains":["api.domain.com"],"prefix":"","role":"vip"}, {"domains":["api.domain.com"],"prefix":"","role":"admin"} ] ``` Notes: 1. JSON must use English double quotes `"`, not Chinese quotes. 2. `DOMAINS`, `ADMIN_PASSWORDS`, and `USER_ROLES` are JSON values, not plain text. #### 5) Bind D1 Path: `Workers & Pages -> Worker -> Settings -> Bindings -> Add Binding` 1. Select type `D1 Database` 2. Variable name must be `DB` 3. Select the D1 created in step 1 #### 6) Bind KV Create first: Path: `Storage & Databases -> KV -> Create Namespace` Then bind it to the Worker: Path: `Workers & Pages -> Worker -> Settings -> Bindings -> Add Binding` 1. Select type `KV Namespace` 2. Variable name must be `KV` 3. Select the namespace you just created #### 7) Configure backend domain (Triggers) Path: `Workers & Pages -> Worker -> Settings -> Triggers` Add a custom domain (you can use `*.workers.dev` first, but it is often unstable in Mainland China). Set it to `api.domain.com` (replace with your backend domain). Verify it works: 1. Open the Worker root URL, it should return `OK` 2. Open `https://api.domain.com/health_check`, it should return `OK` ### 3. Check DNS Proxy Status Path: `Websites -> Your Domain -> DNS` Confirm the temporary mail subdomain record (A/CNAME) is `Proxied` (orange cloud enabled). ### 4. Email Routing Emails sent to your subdomain mailbox must be forwarded to this Worker for processing. Path: `Email -> Email Routing -> Routing rules -> Add catch-all address` Configure as follows: 1. Select `Send to Email Worker` for `Destination/Action` 2. Select the Worker you just deployed 3. Save and wait for propagation If this is your first time enabling Email Routing, Cloudflare will ask you to add/confirm MX-related records. Follow the dashboard prompts. ### 5. Build the Frontend Service Path: `Compute (Workers) -> Workers & Pages -> Create` 1. Select `Pages` 2. Select `Use direct upload` 3. In the official frontend generator page, enter your backend Worker URL (without trailing `/`), then generate and download the zip 4. Go back to Cloudflare Pages and click `Create Pages` 5. Set project name, upload the downloaded zip, then click `Deploy` 6. After deployment, open the Pages project and bind a frontend domain under `Custom Domain` (for example `mail.domain.com`) Frontend generator page: https://temp-mail-docs.awsl.uk/zh/guide/ui/pages If you do not want to use the online generator, you can also download the official frontend package and manually change the backend URL: - Frontend zip: https://github.com/dreamhunter2333/cloudflare_temp_email/releases/latest/download/frontend.zip - Unzip it, modify the default backend URL in `index-*.js`, then repackage and upload Note: `*.workers.dev` is often inaccessible in Mainland China. It is recommended to bind a custom backend domain first, then use that in the frontend generator. ### 6. Verify End-to-End 1. Open the frontend home page, for example `https://mail.domain.com` 2. Generate a temporary mailbox address 3. Send a test email to that address from your regular mailbox 4. Return to the page and confirm it arrives 5. Open `https://mail.domain.com/admin` and log in with a password from `ADMIN_PASSWORDS` to verify backend status At this point, the Cloudflare temporary mail setup is ready to use. --- ## How I Fixed External Access on an IPv6-Only VPS - URL: https://blog.lemonadec.cc/posts/ipv6-only-vps - Date: 2026-02-20 - Language: en - Type: Article While deploying [condev-monitor](https://github.com/Lemonadeccc/condev-monitor), I bought a low-cost VPS to save money. In actual use, I found it was `IPv6-only`, which directly caused the next issue: services that only provide IPv4 endpoints could not be reached. The most obvious symptom was this: after installing Git, cloning a private Alibaba Cloud Codeup repository failed with `fatal: unable to access ...`. Accessing other public internet resources also failed. ## Investigation Process ### 1. Tried Git over SSH first (failed) I first switched to SSH in the usual way and configured keys: ```bash ssh-keygen -t rsa -b 4096 -C "your_email@example.com" cat ~/.ssh/id_rsa.pub ``` After adding the public key to Codeup, cloning over SSH still failed. This suggested the issue was probably not account permission or key configuration. ### 2. Check DNS and the target service's IPv6 support ```bash nslookup codeup.aliyun.com dig codeup.aliyun.com AAAA host codeup.aliyun.com ``` Results: - `nslookup` returned an `A` record (IPv4) - `dig AAAA` returned no record (no IPv6) Conclusion: `codeup.aliyun.com` has no usable IPv6 endpoint. So direct access fails on an IPv6-only server. ## Solution: Add IPv4 outbound capability to an IPv6-only server I chose Cloudflare WARP as an outbound proxy. It tunnels outbound traffic so the server can access IPv4 resources (for example Codeup, GitHub, and Docker Hub). This does not change inbound behavior: - SSH over IPv6 continues to work - IPv6 services exposed by the server are not affected ### 1. Install and enable WARP, then route Git through WARP ```bash curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list sudo apt update sudo apt install -y cloudflare-warp warp-cli register warp-cli set-mode proxy warp-cli connect ``` ```bash git config --global http.proxy http://127.0.0.1:40000 ``` There were many errors, so I switched to the one-click script approach. ### 3. Use a one-click script to quickly set up dual outbound paths To get "native IPv6 + IPv4 tunnel" outbound paths faster, use fscarmen's one-click script: ```bash wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh ``` ## Verification ```bash curl -4 ip.sb curl -6 ip.sb ``` If you get both IPv4 and IPv6 results, the server now has dual outbound capability. ## Final Status - SSH still runs on native IPv6 and remains stable - Access to IPv4-only code hosting and registry services is no longer blocked - The IPv6-only VPS can now handle normal development and deployment tasks --- ## Example MDX - URL: https://blog.lemonadec.cc/posts/gsap-motion-timing - Date: 2026-02-01 - Language: en - Type: Article This post collects practical MDX resource patterns you can paste directly. All local files should live under the `public` directory so they can be referenced as `/path/to/file`. ## 1) Local Image (Markdown) ![Post Cover](/posts/img1.jpg) ## 2) Remote Image (Markdown) ![Remote Placeholder](https://picsum.photos/1200/700) ## 3) Figure + Caption (JSX)
Figure example from local asset
Figure: local asset with caption using semantic HTML.
## 4) Clickable Image [![Click to open full image](/posts/img2.jpg)](/posts/img2.jpg) ## 5) Local Video (MP4/WebM) ## 6) Embedded Video (iframe) ## 7) Audio ## 8) Download/File Link - [Download PDF](https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf) - [Download ZIP Assets](https://github.com/github/gitignore/archive/refs/heads/main.zip) ## 9) Code Block (TypeScript) ```ts import { gsap } from "gsap"; const tl = gsap.timeline({ defaults: { duration: 0.45, ease: "power2.out" } }); tl.addLabel("enter") .from(".card-title", { y: 30, autoAlpha: 0 }, "enter") .from(".card-meta", { y: 20, autoAlpha: 0 }, "enter+=0.08"); ``` ## 10) Code Block (Bash) ```bash npm install gsap npm run dev -- --port 3002 ``` ## 11) Inline Code Use `timeline.addLabel()` to keep motion sequence readable. ## 12) Table (remark-gfm) | Resource | Local Path Example | Remote Support | | -------- | ------------------ | ------------------------ | | Image | `/posts/img1.jpg` | Yes | | Video | `/videos/demo.mp4` | Via iframe or direct URL | | Audio | `/audio/demo.mp3` | Direct URL | | PDF | `/docs/file.pdf` | Yes | ## 13) Task List (remark-gfm) - [x] Article metadata in frontmatter - [x] Code highlighting enabled - [ ] Add real media files in `/public` ## 14) Blockquote / Callout > Keep media paths stable after publish to avoid broken embeds. ## 15) Details / Summary
Click to expand advanced note

A single MDX file can mix Markdown, JSX, code blocks, and rich embeds.

## 16) Raw HTML Block

Custom HTML layout is also valid inside MDX content.

--- ## Vibe Practice Summary - URL: https://blog.lemonadec.cc/posts/vibe-summary - Date: 2026-01-15 - Language: en - Type: Article This post summarizes my experience and lessons from using AI for coding over the past year. Before DeepSeek's breakout in November-December 2025, I mostly used ChatGPT and through ## MCP MCP (Model Context Protocol) defines how applications and AI models exchange contextual information. This allows developers to connect different data sources, tools, and capabilities to AI models in a consistent way, similar to how USB-C lets different devices connect through the same interface. The goal of MCP is to create a universal standard that makes AI application development and integration simpler and more unified. MCP is a product of prompt engineering. More structured context significantly improves model performance. So ecosystem providers usually offer ready-made scenarios that AI can directly use. MCP is also not tied to a specific AI model, and MCP-compatible models can be switched flexibly. - Previously: every AI app integrating every tool required a separate "private integration" implementation (N×M integration hell). - Now: tool providers expose MCP Servers; AI apps implement MCP Clients; everyone interoperates by following the Spec. Previously, if you wanted AI to "read local files + query databases + call GitHub + automate browsers", it basically meant building a plugin/SDK integration set for every AI client, with high maintenance and migration costs. MCP standardizes this through a unified protocol: service providers implement MCP Servers; AI apps implement MCP Clients; they interact by protocol. ### Roles - Host: the product you actually use, such as Claude Desktop or an IDE. The Host manages UX, permissions, and multiple connections. - Client: a connection instance created inside the Host; usually "one Server corresponds to one Client connection." - Server: a local or remote program that provides capabilities, exposing Tools/Resources/Prompts. ### Three Core Primitives - Tools: executable functions (for example, "read file", "send request", "query database"). - Resources: readable contextual data (file content, records, API responses, etc.). - Prompts: reusable prompt templates (conversation structure/system prompt/examples). ### Transport - Common local transport: stdio (Host starts a subprocess and communicates through stdin/stdout). - Common remote transport: Streamable HTTP (optional SSE) (`HTTP POST + optional event stream`), supporting common auth methods (`Bearer token / API key / custom header`). OAuth is also officially recommended for token acquisition. ## Spec The Spec is the "protocol manual" of MCP: it defines handshake behavior, message formats, capability definitions, tool exposure, transport behavior, and more. MCP's data layer is based on JSON-RPC 2.0, and defines lifecycle management, capability negotiation, and the three core primitives: Tools / Resources / Prompts. Official articles: [**What are skills**](https://support.claude.com/en/articles/12512176-what-are-skills), [**Using skills in Claude**](https://support.claude.com/en/articles/12512180-using-skills-in-claude), and [**How to create custom skills**](https://support.claude.com/en/articles/12512198-how-to-create-custom-skills). A more complete reference: [**Agent Skills - Claude Code Docs**](https://code.claude.com/docs/en/skills#create-a-skill) You can register a GitHub repository as a Claude Code plugin marketplace entry by running the following command in Claude Code. ## Skills ## Apifox CLI and Skills ## Midscene --- ## Coolify Deployment Practice - URL: https://blog.lemonadec.cc/posts/coolify-pratice - Date: 2025-10-01 - Language: en - Type: Article # Deployment Plan Research ### Coolify vs Dokploy Coolify is an open-source deployment solution built with Laravel and Docker. It has run stably for years, and its deployment workflow is popular among indie developers, so I tried using Coolify for web deployment. Although Dokploy has more overall advantages than Coolify, Coolify currently has relatively weak Cloudflare support, so I chose the long-standing and stable Coolify here. The detailed practice process is as follows: I rented a limited-time Netcup 4C8G server. After logging in, I first copied my local macOS public key to the server. ```jsx cat ~/.ssh/filename.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys ``` Then set permissions on the server. ```jsx chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys ls -ld ~/.ssh ls -l ~/.ssh/authorized_keys ``` Configure `sshd`. ```jsx vim /etc/ssh/sshd_config PermitRootLogin prohibit-password or true PubkeyAuthentication yes ``` Configure and check the firewall rules required by Coolify. ```jsx sudo ufw status sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 3000/tcp sudo ufw allow 6001/tcp sudo ufw allow 6002/tcp sudo ufw allow 9000:9100/tcp sudo ufw allow 8000/tcp sudo ufw enable sudo ufw status verbose ``` Run the Coolify automated installation script. ```jsx curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` After installation, use your proxy/VPN setup to access port 8000 on the server IP, then configure the Coolify account and permissions. ![image.png](attachment:864d1397-cec5-40c0-8235-b665c7d25281:image.png) ## Actual Deployment ### Create Source Add the default source, rename it to your project name if needed, then select your private/public repository and add it through the GitHub App. ### Create Project After creating the deployment project, add resources from the source created in the previous step. For a simple Next.js project, keep the defaults, for example both base directory and public directory as root `/`. For a monorepo project like `condev-ui`, where the deployed web app lives in a subpackage, you can write `nixpacks.toml` to specify commands. Here the `nixpacks.toml` script is: ```jsx providers = ["node"][phases.setup]; nixPkgs = ["nodejs_22", "pnpm"][phases.install]; cmds = ["pnpm install --frozen-lockfile"][phases.build]; cmds = ["pnpm exec turbo run build"][start]; cmd = "pnpm --filter @condev-ui/site start"; ``` Then push it to the repository and click project deploy. After that, you can access the deployed project through the domain. On subsequent pushes, Coolify will deploy automatically. --- ## GEN-3D-ASSETS Project - URL: https://blog.lemonadec.cc/posts/generate-3D-assest - Date: 2025-08-08 - Language: en - Type: Idea ### Project Repository https://github.com/Lemonadeccc/GEN-3D-ASSESTS In practical implementation, I encountered loading issues with `obj` / `fbx` / `gltf`. A Next.js proxy should not be used, and models or textures should not be loaded through `blob`. Other parts also need to consider real user workflows. ### Page Preview ![image.png](https://imgbed.lemonadec.cc/2026/02/3d-nft.webp) ![image1.png](https://imgbed.lemonadec.cc/2026/02/3d-nft-detail.webp) ## Ideas Mainly using Next.js + R3F + deri? + solidity + Vercel. ## Engineering 1. Technology selection: evaluate contract stacks such as solidity/foundry/harhat. Technically, use Next.js SSR to render 3D models, which I had not used before. For short-term MVP, use CC and other tools for unit tests. 2. Standardization with `commitlint` / `eslint` / `husky`. 3. Use GitHub Actions for CI/CD, combine Qodo for PR review and AI-assisted management, use PockeFlow to generate repository docs, and deploy to Vercel according to Next.js and project requirements. 4. Performance may become tight when loading many 3D models. Optimize by making full use of API request/response loading time, SSR, and Turbopack incremental updates. 5. Optimize GSAP animations and static assets. ## Business Flow 1. Use `meshy.ai` or other generative APIs for 3D generation. 1. Apply for API access; decide whether to use polling or user-configurable strategies during usage. 2. Decide where API configuration should be stored and how to keep keys secure from abuse. 2. Request the API based on prompts. Decide whether to download models before display or show directly. Waiting animations should be polished and interesting. Returned data/models should be selectable, and models should support `autoRotate` during display. 3. After selection, request contracts to put assets on-chain. 4. Deployment needs to be coupled with engineering considerations. ## Value 1. Provide NFT-like personal assets: generate personalized non-fungible 3D assets based on user profile traits and prompt preferences. --- ## condev-monitor Project Deployment Issues - URL: https://blog.lemonadec.cc/posts/condev-monitor - Date: 2025-01-11 - Language: en - Type: Article First, an introduction to the condev-monitor project. This project recreates a Sentry-like frontend monitoring system. It mainly consists of the following parts: an SDK for monitoring errors and performance, an `examples/vanilla` frontend project used to test SDK integration, a `dsn-server` backend service that receives error reports from the SDK, and the dashboard frontend `frontend/monitor` with its backend `backend/monitor`. At the beginning, I planned to deploy with docker-compose on Coolify. After many attempts, the network kept being pruned by Coolify during deployment, and many issues appeared. It may have been a conflict between Caddy in docker-compose and Coolify's own Caddy service. After repeated failures, I bought a new server and switched to a direct docker-compose deployment. The project is deployed with docker-compose and uses many images. In development, it uses two database images, ClickHouse and Postgres, while other parts are developed locally with `pnpm start:dev` and `pnpm dev`. In development, `.env` is maintained by each subproject. For production, the two mainstream deployment options for Next.js are Nixpacks and Docker. For self-hosting needs, Next.js can use the OpenNext adapter to deploy on Cloudflare, and the NestJS backend can be deployed on an internal enterprise host through a tunnel. Or both frontend and backend can be deployed on an internal host with docker-compose. For the two backends, NestJS cannot be deployed without `node_modules`, so backend deployment either needs PM2 on the server or needs `node_modules` bundled into Docker images. I tried running PM2 on the server, and also tried PM2 for the OpenNext project, but errors occurred. So I later chose full docker-compose deployment on the server. By this point, I had already run into pitfalls with both Coolify and the PM2 + docker-compose hybrid approach. I used an Alibaba Cloud 2C2G machine with AliLinux for Docker image deployment, but OOM crashes kept happening. Swap was configured, but still not enough. So I later planned to run the backend with PM2 and containerize only ClickHouse and Postgres, but after trying it, the deployment steps were too cumbersome, so I dropped it and switched to full docker-compose deployment. In the dashboard NestJS backend, `argon2` failed to compile on Alibaba Cloud with the default Python 3.6. I tried switching to Python 3.7 and recompiling, but it still failed. Since this kept happening, I directly replaced that encryption dependency with `bcryptjs`. Another issue was during docker-compose deployment on Alibaba Cloud: when using the older `nest-modules/mailer` in the dashboard NestJS backend, it reported missing CSS-in-JS dependencies. I found a solution in GitHub issues, but it was not very standard and the process was tedious. Future maintenance would likely be even harder, so I switched to `nodemailer`. OOM issues kept happening on Alibaba Cloud, so I moved to an external Netcup 4C6G machine. This avoided complicated ICP filing and Docker image setup, and also avoided the issue of OpenAI services being unavailable in China during later development of other AI projects (the Cloudflare Worker workaround is no longer effective). Full docker-compose image deployment worked normally, but testing showed email sending and receiving did not work. After testing with machine scripts, I found the server did not support SMTP email sending. So based on the previous `nodemailer` setup that used 163 SMTP, I now prioritize Resend's HTTP email service, and fall back to SMTP when HTTP sending fails. This ensures email service keeps working when severe errors occur. So far, these are the errors and pitfalls encountered in dependency replacement and deployment for this project. --- ## 应用 AI 流程总结 - URL: https://blog.lemonadec.cc/posts/new-ai-tools-for-me?lang=zh - Date: 2026-03-01 - Language: zh - Type: 文章 这篇文章不是工具清单,而是我在真实项目里反复迭代后沉淀下来的一套工作方法。 流程是先把约束写清楚,再让多模型并行执行,最后通过统一审查收口。 ## 一、设计阶段 设计阶段对齐信息架构,快速产出可迭代初稿。 ### 1) 线框草图 - [wiretext](https://wiretext.app/):快速把页面结构写成线框,适合先确认信息层级。 - [mockdown](https://www.mockdown.design/):用文本表达页面块级布局,适合早期讨论和需求澄清。 ### 2) UI 套壳与变体 - [Pencil](https://www.pencil.dev/):通过 prompt 生成可编辑界面稿。 - [variant ai](https://www.variant.ai/):先找接近风格,再用 prompt 调整;导出 `.js` 后继续用 Claude Code 或 Codex 做结构细化。 ## 二、开发阶段 ### 1) 多 Agent + Git Worktree 的基线做法 我当前面对简单需求拆分: 1. 一个需求拆成 2-4 个相对独立子任务。 2. 每个子任务绑定独立 worktree 和独立会话。 3. 先合并可验证的小增量,再做跨模块收敛。 这能显著降低上下文污染和任务互扰。 但也有边界:任务耦合度过高时,过度拆分 worktree 会放大集成成本。 ### 2) 第三方工具生态 过去我常用: - [superset](https://github.com/superset-sh/superset):并行 worktree 编排工具。 - [happy](https://github.com/slopus/happy):远程控制 cc。 现在 Claude 官方已经覆盖了多 worktree 和部分远程能力,这类工具更适合作为其他 CLI 增强工具。 ## 三、CCG Workflow:把多模型协作流程化 `ccg-workflow` 在我的体系里承担“调度层”角色:Claude Code 负责编排,前端任务优先路由给 Gemini,后端任务优先路由给 Codex,最后由 Claude 统一审核并落地 patch。 ### 1) 安装与前置 ```bash npx ccg-workflow ``` - 需要 `Node.js 20+`。 - 可选安装 `Codex CLI`(偏后端)和 `Gemini CLI`(偏前端)。 ### 2) 常用命令 - 全流程:`/ccg:workflow` - 规划 + 执行分离:`/ccg:plan` + `/ccg:execute` - 面向任务:`/ccg:frontend`、`/ccg:backend`、`/ccg:debug`、`/ccg:optimize`、`/ccg:review` 先计划再执行: ```bash /ccg:plan 实现用户认证功能 /ccg:execute .claude/plan/user-auth.md ``` 这种方式可以降低会话切换带来的损耗,并减少实现阶段的目标漂移。 ### 3) ccg 内置能力 - 规范驱动(`/ccg:spec-*`): - 适合约束多、容易偏题的复杂需求。 - 价值是把“自由生成”收敛为“约束执行”。 - 并行实施(`/ccg:team-*`): - 适合可拆成 3 个以上独立模块的任务。 - 价值是通过 `/clear` + 文件状态传递减少上下文串扰。 ### 4) 配置与避坑 - 在 `~/.claude/settings.json` 调整超时参数(如 `CODEX_TIMEOUT`、`BASH_DEFAULT_TIMEOUT_MS`)。 - MCP 工具按复杂度选配:ContextWeaver + Context7 / Playwright / DeepWiki / Exa。 ## 四、Skills 可复用流程 常用 skills 资源: - [skills 官方](https://skills.sh/) - [superpowers](https://github.com/obra/superpowers) - [claude-mem](https://github.com/thedotmack/claude-mem/tree/main) - [react-best-practices](https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices) 对应定位: - `superpowers`:流程编排(自动计划、阶段执行、收尾校验)。 - `claude-mem`:上下文压缩与记忆管理(适合长链路任务)。 - `react-best-practices`:实现阶段的性能与代码质量约束。 ## 五、MCP 能力拓展 我目前主要使用 Lighthouse MCP: - `@danielsogl/lighthouse-mcp`:功能完整,支持 Core Web Vitals、budget 等。 实践里有两个高频坑: 1. 跑 Lighthouse 时要明确要求 LLM 同时测“桌面端 + 移动端”,否则很多自动化流程只测移动端。 2. 自动化跑分和 DevTools 手动跑分会存在差异,建议以趋势和瓶颈定位为主,不要过度解读单次绝对分数。 如果站点托管在 Cloudflare 且出现爬虫/审计访问异常,先检查 `robots.txt` 与缓存策略,必要时清理 `robots.txt` 相关缓存再重试。 ## 六、测试与评审流水线 ### 1) 在 prompt 中明确三层测试要求 实现完成后我会直接下这种可复用指令: ```text 请基于当前变更补齐并执行测试,要求: 1) 单元测试(unit tests):覆盖核心函数、边界条件、异常路径。 2) 集成测试(integration tests):覆盖模块间协作、数据流与接口契约。 3) 端到端测试(e2e tests):覆盖关键用户路径(成功流 + 失败流)。 执行要求: - 先写测试再修复实现,直到全部通过。 - 输出每类测试的新增用例清单、执行命令和结果摘要。 - 标注当前未覆盖风险点和建议补测项。 ``` ### 2) 多模型交叉 code review 测试通过后,我会让不同模型分别做 review,重点关注: 1. 潜在 bug 与边界问题。 2. 可读性与可维护性。 3. 性能、复杂度与扩展性风险。 4. 测试覆盖是否与业务风险匹配。 多模型 review 的核心收益是降低单模型盲区。 ### 3) 人工 review AI review 之后,我会做一轮人工 review,主要确认: 1. 需求是否真正闭环,而不是只满足字面描述。 2. 改动是否引入潜在回归。 3. 命名、边界、错误处理是否符合团队约定。 4. 测试是否覆盖最高风险路径。 人工 review 的作用不是重复 AI 结论,而是做业务上下文判断与最终风险兜底。 ### 4) CI 后接 GitHub App 自动审查 PR 提交并通过 CI 后,我会再接一轮 GitHub App 自动审查,常用包括: - [Coderabbit](https://coderabbit.ai/) - [Gemini Code Assist](https://codeassist.google/) - [qodo](https://www.qodo.ai/) 我自己也在 vibe 一个面向测试阶段的 [pr-agent](https://github.com/condevtools/pr-agent),目标是把“测试结果 + 风险点 + review 建议”自动汇总到 PR/Issue,提升评审与决策效率。 ## 七、当前可复用的端到端流程 1. 用线框工具明确信息层级和页面结构。 2. 用 UI 生成工具快速得到可编辑初稿。 3. 开发阶段以 MVP 为先,按 worktree 并行推进独立子任务。 4. 复杂需求先用 `/ccg:plan` 或 `/ccg:spec-*` 锁定约束,再进入实现。 5. 合并前执行统一 review(`/ccg:review` + 人工抽检),最后做稳态重构(健壮性、可维护性、边界处理)。 这套流程的核心收益是:前期速度快,中期质量稳,后期维护成本可控。 --- ## Cloudflare R2 + PicGo 搭建图床 - URL: https://blog.lemonadec.cc/posts/cloudflare-r2-imgbed?lang=zh - Date: 2026-02-26 - Language: zh - Type: 文章 Cloudflare R2 免费计划每月有 10GB,用来做个人图床基本够用。 ![free-tier](https://imgbed.lemonadec.cc/2026/02/blog-cloudflare-r2-imgbed-free-tier.png) ### 一、创建 R2 存储桶 1. 进入 Cloudflare 控制台,打开 `R2 -> 创建存储桶`。 2. 输入存储桶名称并创建。 3. 进入该存储桶,打开 `设置 -> 添加自定义域`,输入自定义域名。 4. 确认后会生成对应 DNS 记录。 5. 先手动上传一个文件做测试,确认桶可正常读写。 ### 二、创建 API 令牌 路径:`R2 -> Account Details -> Manage API Tokens -> 创建令牌` 1. 令牌权限选择 `对象读和写`。 2. 作用范围选择 `仅应用于特定存储桶`。 3. 创建后保存好以下信息: - `访问密钥 ID` - `机密访问密钥` ### 三、PicGo 设置 1. 下载并安装 [PicGo](https://github.com/Molunerfinn/PicGo)。 2. 在 PicGo 插件市场安装 `S3` 插件。 3. 打开 `PicGo -> 图床设置 -> Amazon S3`,新建一个配置。 参数对应关系: | PicGo 字段 | 填写内容 | | --- | --- | | 应用密钥 ID | R2 的 `访问密钥 ID` | | 应用秘钥 | R2 的 `机密访问密钥` | | 桶名 | R2 页面中的存储桶名称 | | 文件路径 | `{year}/{month}/{fileName}.{extName}` | | 自定义节点 | R2 页面提供的 S3 终结点(Endpoint) | | 拒绝无效 TLS 证书链接 | `yes` | | ACL 访问控制列表 | `public-read` | ### 四、上传验证 1. 在 PicGo 上传区选择图片并上传。 2. 在 Cloudflare R2 对应存储桶确认文件已生成。 3. 在 PicGo 中复制上传后链接并访问测试。 --- ## Cloudflare Tunnel + Zero Trust 稳定接入 Netcup VPS SSH - URL: https://blog.lemonadec.cc/posts/cloudflare-tunnel-de-vps?lang=zh - Date: 2026-02-25 - Language: zh - Type: 文章 当我访问自己的 openclaw 时,飞书侧一直没有回复,于是排查了一轮服务器。 最终发现问题不是 `sshd` 挂了,而是跨境链路(德国线路到联通)不稳定。 最后采用的方案是:在服务器部署 `cloudflared`,把 `ssh-de.condevtools.com` 通过 Tunnel 映射到 `localhost:22`,本地使用 `cloudflared access ssh` 连接。 这样 SSH 不再依赖直连 `22` 端口,稳定性和可控性都更好。 ### 现状确认 服务器厂商 VNC 可进入,SSH 服务 active,`22` 端口监听正常,日志中有 `Connection reset by peer [preauth]`。 ```bash systemctl status ssh ss -tlnp | grep sshd ufw status # 或 iptables -S / nft list ruleset journalctl -u ssh -n 100 --no-pager ``` 检查要点: - `systemctl status ssh`:看 SSH 服务是否在运行。 - `Active: active (running)`:服务正常启动。 - `inactive/failed`:服务未启动,先修服务(配置、密钥、启动失败等)。 - `ss -tlnp | grep sshd`:看 SSH 是否监听端口。 - `0.0.0.0:22` 和 `[::]:22`:监听所有 IPv4/IPv6 地址。 - 只有 `127.0.0.1:22`:只监听本机,外部无法连接。 - 无输出:未监听(服务没起或端口改了)。 - `ufw status`:看系统防火墙是否拦截 SSH。 - `Status: inactive`:系统层未拦截。 - `active` 且没有 `22/tcp ALLOW`(或你改后的端口)会被拦。 - `journalctl -u ssh -n 100 --no-pager`:看认证和连接日志。 - `Accepted publickey`:登录成功。 - `Failed password`:账号或密码问题。 - `Connection reset by peer [preauth]`:连接到达服务器,但认证前被链路或中间设备重置,常见于网络路径问题。 结论:服务正常 + 端口正常 + UFW 未拦 + 日志出现 `preauth reset`,说明更像链路问题,而不是服务器 SSH 配置故障。 ### 方案 #### 1. 通过香港机中转 SSH 先 SSH 到香港机,再从香港机连接德国机;或者在香港机上搭 WebSSH。 注意:公共 WebSSH 不安全,可能泄露凭据并暴露攻击面。 ```sshconfig # ~/.ssh/config Host hk HostName 香港机IP User your_user Port 22 IdentityFile ~/.ssh/id_rsa Host de-via-hk HostName 德国机IP User your_user Port 22 ProxyJump hk IdentityFile ~/.ssh/id_rsa ``` ```bash ssh de-via-hk ``` 也可以参考这个教程:[加便宜香港机做中转](https://www.vircs.com/blogs/52),由于成本问题转而搜寻其他方案。 #### 2. 用 `sshx` 临时网页终端 可通过 VNC 在服务器上安装并运行 [sshx](https://github.com/ekzhang/sshx),再从本地浏览器打开生成的链接。 ```bash curl -sSf https://sshx.io/get | sh sshx ``` ![sshx](https://imgbed.lemonadec.cc/2026/02/sshx.png) 这个方案可应急,但实际使用中可能出现断流,需重复开启 vnc 运行 sshx ,因此后续改为 Cloudflare Tunnel。 #### 3. Cloudflare Tunnel 与 cloudflared Cloudflare Tunnel 是“由源站主动发起”的反向隧道: 服务器运行 `cloudflared` 后,会主动连接 Cloudflare 边缘,再把指定域名(如 `ssh-de.condevtools.com`)的流量转发到本机服务(如 `localhost:22`)。 它主要解决三类问题: - 跨境直连不稳定 - 端口被运营商或网络策略干扰 - 公网暴露 SSH 端口的安全风险 工作原理可概括为“出站建隧道 + 边缘鉴权 + 回源转发”:用户先访问 Cloudflare 边缘,经过 Zero Trust Access 身份校验后,再通过已建立的 Tunnel 到达源站。 因此即使关闭源站公网 SSH 端口,也能保留稳定且更安全的远程运维通道。 `Cloudflare Tunnel` 是服务本身,`cloudflared` 是官方客户端:前者定义能力,后者负责建隧道、发起接入并转发流量。 ### 服务器端 #### 1. 安装 cloudflared(Ubuntu 24.04) ```bash sudo apt-get update sudo apt-get install -y cloudflared cloudflared --version ``` #### 2. 登录 Cloudflare 并生成 `/root/.cloudflared/cert.pem` ```bash cloudflared tunnel login ls -l /root/.cloudflared/cert.pem ``` #### 3. 创建 Tunnel 并绑定 SSH 子域名 ```bash cloudflared tunnel create de-ssh cloudflared tunnel list cloudflared tunnel route dns de-ssh ssh-de.condevtools.com ``` #### 4. 生成配置文件 ```bash TUNNEL_ID=$(cloudflared tunnel list | awk '$2=="de-ssh"{print $1}') cat >/root/.cloudflared/config.yml < Access -> Applications -> Add application -> Self-hosted` 2. `Domain` 填:`ssh-de.condevtools.com` 3. `Policy` 仅允许你自己的邮箱/账号,建议开启 MFA ### 本地 Mac #### 1. 安装客户端 ```bash brew install cloudflared cloudflared --version ``` #### 2. 直接连接测试 ```bash ssh -o "ProxyCommand=$(which cloudflared) access ssh --hostname %h" root@ssh-de.condevtools.com ``` #### 3. 可选:写入 `~/.ssh/config`,以后直接 `ssh de-cf` ```sshconfig Host de-cf HostName ssh-de.condevtools.com User root ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h ``` ```bash ssh de-cf ``` --- ## openclaw + 飞书部署指南 - URL: https://blog.lemonadec.cc/posts/openclaw-feishu?lang=zh - Date: 2026-02-21 - Language: zh - Type: 文章 - zsh:https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH - oh-my-zsh:https://ohmyz.sh/ - 系统更新:apt update - 系统升级:apt upgrade - openclaw 安装:https://docs.openclaw.ai/zh-CN/install - 飞书:https://docs.openclaw.ai/zh-CN/channels/feishu - 创建应用:https://open.feishu.cn/app - 开通机器人功能 - 批量添加权限 - 安装插件:https://github.com/m1heng/Clawdbot-feishu - openclaw plugins install @m1heng-clawd/feishu - 配置渠道:https://docs.openclaw.ai/zh-CN/channels/feishu - openclaw channels add - openclaw gateway restart - 应用设置(开发者后台): - 事件订阅(事件与回调):订阅长连接 - 添加事件:im.message.receive_v1 - 工作台(手机 / 功能菜单-消息-工作台) - 可能需要验证 pairing 码: openclaw pairing approve feishu pairing_code - VPS: - [Netcup](https://www.netcup.com/en/) --- ## Cloudflare 搭建临时邮箱 - URL: https://blog.lemonadec.cc/posts/cloudflare-temporary-mail?lang=zh - Date: 2026-02-20 - Language: zh - Type: 文章 很多平台注册都要邮箱验证。常规邮箱前缀基本固定,想做测试、分流或者临时注册某些网站就很不方便。 - 开源项目:https://github.com/dreamhunter2333/cloudflare_temp_email - 官方文档:https://temp-mail-docs.awsl.uk ### 方案结构 这套临时邮箱核心是 4 件事: 1. `Worker`:处理收信逻辑、邮箱生成、后台接口 2. `D1`:存邮件和地址数据 3. `KV`:存会话等短期状态 4. `Email Routing + 自定义域名`:把 `*@你的域名` 的邮件路由到 Worker ### 前置准备 1. 一个已托管在 Cloudflare 的域名(例如 `mail.domain.com`) 2. Cloudflare 账号有 Workers / D1 / Email Routing 权限 3. 准备一个可用子域名专门给临时邮箱 4. 建议提前规划两个子域名: - 后端 Worker:`api.domain.com` - 前端 Pages:`mail.domain.com` ### 一、先在 Cloudflare 创建 D1 数据库 路径:`Workers & Pages -> D1 SQL Database -> Create` 1. 数据库名称填 `temp-mail`(或你自己的名字) 2. 创建后进入该数据库详情页 3. 打开 `Console` 或 `Query` 页面 4. 把项目里的 [docs/schema.sql](https://github.com/dreamhunter2333/cloudflare_temp_email/blob/main/db/schema.sql) 内容复制进去执行 到这里数据库表就初始化好了。 ### 二、部署邮箱服务后端 #### 1) 新建 Worker 路径:`Compute (Workers) -> Workers & Pages -> Create -> Worker -> Create Worker` 1. 先创建一个新的 Worker 2. 命名后点击 `Deploy` #### 2) 设置兼容性标志 路径:`Workers & Pages -> Worker -> Settings -> Runtime` 1. 在 `Compatibility flags` 里手动新增:`nodejs_compat` 2. `Compatibility date` 设为不早于 `2024-09-23` #### 3) 上传后端 worker.js 并部署 1. 下载后端文件:https://github.com/dreamhunter2333/cloudflare_temp_email/releases/latest/download/worker.js 2. 回到路径:`Workers & Pages -> Worker -> Overview -> Edit Code` 3. 删除默认文件 4. 左侧点 `Explorer`,在文件列表区域右键 -> `Upload`,上传 `worker.js` 5. 点右上角 `Deploy` #### 4) Variables and Secrets 里逐项加变量 路径:`Workers & Pages -> Worker -> Settings -> Variables and Secrets` 按“一个一个添加变量”的方式配置。 先配这一组最小可运行变量(推荐): | 变量名 | 类型 | 示例值 | 说明 | | --- | --- | --- | --- | | `DOMAINS` | JSON | `["api.domain.com"]` | 可用域名列表,支持多个 | | `JWT_SECRET` | 文本 | `your_jwt_secret` | JWT 密钥,务必换成随机强密码 | | `ADMIN_PASSWORDS` | JSON | `["your_password"]` | 后台密码列表,至少配一个 | | `ENABLE_USER_CREATE_EMAIL` | 文本 | `true` | 允许用户创建地址 | | `ENABLE_USER_DELETE_EMAIL` | 文本 | `true` | 允许用户删除邮件 | | `ENABLE_ADDRESS_PASSWORD` | 文本 | `true` | 启用邮箱地址密码登录 | 常用扩展变量(按需加): | 变量名 | 类型 | 示例值 | 说明 | | --- | --- | --- | --- | | `ADMIN_USER_ROLE` | 文本 | `admin` | 管理员角色名 | | `NO_LIMIT_SEND_ROLE` | 文本 | `admin` | 无限发信角色 | | `ENABLE_AUTO_REPLY` | 文本 | `false` | 自动回复开关 | | `DEFAULT_DOMAINS` | JSON | `["api.domain.com"]` | 未登录用户默认可用域名 | | `USER_ROLES` | JSON | 见下方示例 | 自定义角色与域名权限 | 可直接复制的变量值示例(避免格式报错): ```text DOMAINS=["api.domain.com"] ADMIN_PASSWORDS=["your_password","your_password_two"] DEFAULT_DOMAINS=["api.domain.com"] USER_ROLES=[ {"domains":["api.domain.com"],"prefix":"","role":"vip"}, {"domains":["api.domain.com"],"prefix":"","role":"admin"} ] ``` 注意: 1. JSON 必须用英文双引号 `"`,不要用中文引号。 2. `DOMAINS`、`ADMIN_PASSWORDS`、`USER_ROLES` 都是 JSON,不是普通文本。 #### 5) 绑定 D1 路径:`Workers & Pages -> Worker -> Settings -> Bindings -> Add Binding` 1. Type 选 `D1 Database` 2. Variable name 必须是 `DB` 3. Database 选择你第一步创建的 D1 #### 6) 绑定 KV 先创建: 路径:`Storage & Databases -> KV -> Create Namespace` 再绑定到 Worker: 路径:`Workers & Pages -> Worker -> Settings -> Bindings -> Add Binding` 1. Type 选 `KV Namespace` 2. Variable name 必须是 `KV` 3. Namespace 选刚创建的命名空间 #### 7) 配后端域名(Triggers) 路径:`Workers & Pages -> Worker -> Settings -> Triggers` 添加自定义域名(也可先用 `*.workers.dev`,但中国网络下不稳定)。 填写:`api.domain.com`(替换成你的后端域名) 验证是否成功: 1. 打开 Worker 根地址,返回 `OK` 2. 打开 `https://api.domain.com/health_check`,返回 `OK` ### 三、检查 DNS 代理状态 路径:`Websites -> 你的域名 -> DNS` 确认临时邮箱子域记录(A/CNAME)为 `Proxied`(橙云开启) ### 四、Email Routing 发给你子域名邮箱的邮件,需要在这里转发给 Worker 处理。 路径:`Email -> Email Routing -> Routing rules -> Add catch-all address` 按下面配置: 1. `Destination/Action` 选择 `Send to Email Worker` 2. 选择你刚部署的 Worker 3. 保存并等待生效 如果你是首次启用 Email Routing,Cloudflare 会要求添加/确认 MX 相关记录,按面板提示补齐即可。 ### 五、搭建前端服务 路径:`Compute (Workers) -> Workers & Pages -> Create` 1. 选择 `Pages` 2. 选择 `Use direct upload` 3. 在官方文档前端页面里的生成器输入你后端 Worker 地址(不要带最后的 `/`),点击生成并下载 zip 4. 回到 Cloudflare Pages,点击 `Create Pages` 5. 填写项目名,上传刚下载的 zip,点击 `Deploy` 6. 部署完成后进入该 Pages 项目,点击 `Custom Domain` 绑定前端域名(例如 `mail.domain.com`) 前端生成器页面:https://temp-mail-docs.awsl.uk/zh/guide/ui/pages 如果你不想用在线生成器,也可以直接下载官方前端包再手动改后端地址: - 前端 zip:https://github.com/dreamhunter2333/cloudflare_temp_email/releases/latest/download/frontend.zip - 解压后修改 `index-*.js` 里默认后端地址为Worker 域名,再重新打包上传 注意: `*.workers.dev` 在中国网络环境下经常不可用,后端建议绑定自定义域名后再填到前端生成器里。 ### 六、验证是否跑通 1. 打开前端域名首页,例如 `https://mail.domain.com` 2. 生成一个临时邮箱地址 3. 从你常用邮箱给这个地址发一封测试邮件 4. 回到页面看是否收到 5. 打开 `https://mail.domain.com/admin`,用 `ADMIN_PASSWORDS` 里的密码登录后台确认数据状态 到这里,这套 Cloudflare 临时邮箱就算可用了。 --- ## IPv6-Only VPS 无法访问外网的解决记录 - URL: https://blog.lemonadec.cc/posts/ipv6-only-vps?lang=zh - Date: 2026-02-20 - Language: zh - Type: 文章 在部署 [condev-monitor](https://github.com/Lemonadeccc/condev-monitor) 时,我为了节约成本购买了一台便宜 VPS。实际使用后发现它是 `IPv6-only`,这也直接引出了后续的问题:部分仅提供 IPv4 入口的服务无法访问。 最明显的症状是:安装好 Git 后,`clone` 阿里云效 Codeup 私有仓库时报错 `fatal: unable to access ...`。并且访问其他外网资源报错。 ## 排查过程 ### 1. 先尝试 Git SSH 协议(失败) 我先按常规流程切换到 SSH 协议并配置密钥: ```bash ssh-keygen -t rsa -b 4096 -C "your_email@example.com" cat ~/.ssh/id_rsa.pub ``` 把公钥添加到 Codeup 后继续用 SSH 克隆,依旧失败。说明问题大概率不在账号权限或密钥本身。 ### 2. 检查 DNS 和目标站点的 IPv6 支持 ```bash nslookup codeup.aliyun.com dig codeup.aliyun.com AAAA host codeup.aliyun.com ``` 检查结果: - `nslookup` 返回 `A` 记录(IPv4) - `dig AAAA` 没有记录(无 IPv6) 结论:`codeup.aliyun.com` 没有可用的 IPv6 入口。 因此在 IPv6-only 服务器上,直连会失败。 ## 解决方案:给 IPv6-only 服务器补 IPv4 出站能力 我选择 Cloudflare WARP 作为出站代理。它的作用是把服务器的出站流量通过隧道转发,从而访问 IPv4 资源(例如 Codeup、GitHub、Docker Hub)。 这不会改变服务器的入站能力: - 你原本通过 IPv6 做 SSH 仍然可用 - 服务器对外提供的 IPv6 服务也不受影响 ### 1. 安装并启用 WARP 并 让 Git 走 WARP 代理 ```bash curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list sudo apt update sudo apt install -y cloudflare-warp warp-cli register warp-cli set-mode proxy warp-cli connect ``` ```bash git config --global http.proxy http://127.0.0.1:40000 ``` 报错很多,选用一键脚本方案 ### 3. 使用一键脚本快速配置双出口 更快得到“IPv6 原生 + IPv4 隧道”双出口,使用 fscarmen 的一键脚本: ```bash wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh ``` ## 验证结果 ```bash curl -4 ip.sb curl -6 ip.sb ``` 当你同时拿到 IPv4 与 IPv6 返回结果时,说明当前机器已经具备双出口能力。 ## 最终状态 - SSH 继续走原生 IPv6,连接稳定 - 访问仅 IPv4 的代码托管和镜像源不再受限 - IPv6-only 服务器可以正常完成日常开发与部署任务 --- ## MDX 资源示例 - URL: https://blog.lemonadec.cc/posts/gsap-motion-timing?lang=zh - Date: 2026-02-01 - Language: zh - Type: 文章 这篇文章整理了可直接复制的 MDX 资源模板。 本地文件建议统一放在 `public` 目录下,并通过 `/path/to/file` 进行引用。 ## 1) Local Image (Markdown) ![Post Cover](/posts/img1.jpg) ## 2) Remote Image (Markdown) ![Remote Placeholder](https://picsum.photos/1200/700) ## 3) Figure + Caption (JSX)
Figure example from local asset
Figure: local asset with caption using semantic HTML.
## 4) Clickable Image [![Click to open full image](/posts/img2.jpg)](/posts/img2.jpg) ## 5) Local Video (MP4/WebM) ## 6) Embedded Video (iframe) ## 7) Audio ## 8) Download/File Link - [Download PDF](https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf) - [Download ZIP Assets](https://github.com/github/gitignore/archive/refs/heads/main.zip) ## 9) Code Block (TypeScript) ```ts import { gsap } from "gsap"; const tl = gsap.timeline({ defaults: { duration: 0.45, ease: "power2.out" } }); tl.addLabel("enter") .from(".card-title", { y: 30, autoAlpha: 0 }, "enter") .from(".card-meta", { y: 20, autoAlpha: 0 }, "enter+=0.08"); ``` ## 10) Code Block (Bash) ```bash npm install gsap npm run dev -- --port 3002 ``` ## 11) Inline Code Use `timeline.addLabel()` to keep motion sequence readable. ## 12) Table (remark-gfm) | Resource | Local Path Example | Remote Support | | -------- | ------------------ | ------------------------ | | Image | `/posts/img1.jpg` | Yes | | Video | `/videos/demo.mp4` | Via iframe or direct URL | | Audio | `/audio/demo.mp3` | Direct URL | | PDF | `/docs/file.pdf` | Yes | ## 13) Task List (remark-gfm) - [x] Article metadata in frontmatter - [x] Code highlighting enabled - [ ] Add real media files in `/public` ## 14) Blockquote / Callout > Keep media paths stable after publish to avoid broken embeds. ## 15) Details / Summary
Click to expand advanced note

A single MDX file can mix Markdown, JSX, code blocks, and rich embeds.

## 16) Raw HTML Block

Custom HTML layout is also valid inside MDX content.

--- ## Vibe 实践总结 - URL: https://blog.lemonadec.cc/posts/vibe-summary?lang=zh - Date: 2026-01-15 - Language: zh - Type: 文章 开一篇文章总结一下过去一年在使用AI进行coding的经验和心得。 在二五年一二月之前,deepseek未爆发时期,大多还是使用chatgpt以及通过 ## MCP MCP(Model Context Protocol)定义了应用程序和 AI 模型之间交换上下文信息的方式。这使得开发者能够以一致的方式将各种数据源、工具和功能连接到 AI 模型,就像 USB-C 让不同设备能够通过相同的接口连接一样。MCP 的目标是创建一个通用标准,使 AI 应用程序的开发和集成变得更加简单和统一。 MCP 是 Prompt engineer 的产物,更结构化上下文信息对模型的提升是显著的。所以生态库提供者一般提供现成场景,可以让AI可以直接使用。而且 MCP 不限定于特定的AI模型,支持 MCP 的模型都可以灵活切换。 - 以前:每个 AI 应用要接每个工具,都要单独写一套“私有对接”(N×M 集成地狱)。 - 现在:工具方提供 MCP Server;AI 应用做 MCP Client;大家都按 Spec 说话,就能互通。 以前你想让 AI “读本地文件 + 查数据库 + 调 GitHub + 自动化浏览器”,基本等于要为每个 AI 客户端做一套插件/SDK 对接,维护成本高、迁移成本高。 MCP 用统一协议把这件事标准化:服务提供方实现 MCP Server;AI 应用实现 MCP Client;按协议交互即可。 ### 角色 - Host(宿主应用):你实际在用的产品,比如 Claude Desktop、IDE。Host 管理体验、权限、多个连接。 - Client(客户端):Host 里创建的连接实例;通常“一个 Server 对应一个 Client 连接”。 - Server(服务端):提供能力的一段程序(本地或远程),暴露 Tools/Resources/Prompts。 ### 三个核心原语(Primitives) - Tools:可执行函数(例如“读文件”“发请求”“查库”)。 - Resources:可读取的上下文数据(文件内容、记录、API 响应等)。 - Prompts:可复用提示模板(对话结构/系统提示/示例)。 ### 传输(Transport) - 本地常用:stdio(Host 启一个子进程,通过标准输入输出通信) - 远程常用:Streamable HTTP(可选 SSE)(HTTP POST + 可选事件流),并支持常见鉴权方式(Bearer token / API key / 自定义 header),官方也推荐 OAuth 获取 token。 ## Spec Spec 就是 MCP 的“协议说明书”:规定双方如何握手、怎么发消息、有哪些能力、如何暴露工具、如何传输等。MCP 的数据层基于 JSON‑RPC 2.0,并定义了生命周期管理、能力协商、以及 3 个核心原语(Primitives):Tools / Resources / Prompts。 官方文章:[\*\*什么是技能](https://support.claude.com/en/articles/12512176-what-are-skills)** 、[**如何在 Claude 中使用](https://support.claude.com/en/articles/12512180-using-skills-in-claude)** 及 [**如何创建自定义技能**](https://support.claude.com/en/articles/12512198-how-to-create-custom-skills) 更全面的一篇:[**Agent Skills - Claude Code Docs\*\*](https://code.claude.com/docs/en/skills#create-a-skill) 可以通过在 Claude Code 中运行以下命令,将 GitHub 存储库注册为 Claude Code 插件市场 ## Skills ## Apifox CLI and Skills ## Midscene --- ## Coolify 部署实践 - URL: https://blog.lemonadec.cc/posts/coolify-pratice?lang=zh - Date: 2025-10-01 - Language: zh - Type: 文章 # 部署方案调研 ### Coolify vs Dokploy coolify作为使用larvel基于docker开发的开源部署方案,稳定运行多年且其部署方案深受个人开发者喜爱,所以尝试使用coolify解决网页部署。虽然总体上dokploy比coolify有更多的优点,但是目前coolify对cloudflare支持还是比较差一些所以我这里用了开源比较久的稳定老牌coolify。 以下为具体实践过程: 开了一台netcup限时特惠的4c8g服务器,进入服务器后首先配置本地mac公钥到服务器上 ```jsx cat ~/.ssh/filename.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys ``` 然后在服务器上添加权限 ```jsx chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys ls -ld ~/.ssh ls -l ~/.ssh/authorized_keys ``` 配置sshd ```jsx vim /etc/ssh/sshd_config PermitRootLogin prohibit-password or true PubkeyAuthentication yes ``` 配置coolify所需防火墙并检查 ```jsx sudo ufw status sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 3000/tcp sudo ufw allow 6001/tcp sudo ufw allow 6002/tcp sudo ufw allow 9000:9100/tcp sudo ufw allow 8000/tcp sudo ufw enable sudo ufw status verbose ``` 运行coolify自动化安装脚本 ```jsx curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` 安装完成后在梯子配置可访问ip的8000端口随后设置coolify权限账号 ![image.png](attachment:864d1397-cec5-40c0-8235-b665c7d25281:image.png) ## 实际部署 ### 创建source 新增默认source,其名称可改为你所部署项目名称,然后默认选中privte/public的仓库并用github app新增。 ### 创建project 新增部署项目后需要添加上一步所创建的source的资源。如果是简单nextjs项目则保持默认,比如base directory以及publick directory都保持根目录/,如果是condev-ui这样的monorepo项目,所部署的网页在某一个子包里,可以编写nixpacks.toml去指定命令。这里nixpacks.toml的脚本写的为 ```jsx providers = ["node"][phases.setup]; nixPkgs = ["nodejs_22", "pnpm"][phases.install]; cmds = ["pnpm install --frozen-lockfile"][phases.build]; cmds = ["pnpm exec turbo run build"][start]; cmd = "pnpm --filter @condev-ui/site start"; ``` 然后push到仓库里面,点击project deploy。然后就可以在domain里面访问部署的项目了。等到下次push到仓库中coolify会自动部署。 --- ## GEN-3D-ASSETS 项目 - URL: https://blog.lemonadec.cc/posts/generate-3D-assest?lang=zh - Date: 2025-08-08 - Language: zh - Type: 想法 ### 项目地址 https://github.com/Lemonadeccc/GEN-3D-ASSESTS 实际应用过程中遇到了obj / fbx / gltf load的问题,不应该使用nextjs代理,也不应该使用blob去load模型或者纹理。其他部分要考虑用户使用逻辑。 ### 页面效果 ![image.png](https://imgbed.lemonadec.cc/2026/02/3d-nft.webp) ![image1.png](https://imgbed.lemonadec.cc/2026/02/3d-nft-detail.webp) ## 想法 主要使用nextjs + r3f + deri? + solidy + vercel ## 工程 1. 技术选型,solidy/foundry/harhat等其他合约选型,技术上使用没用过的nextjs的ssr渲染3d模型。短期mvp使用cc等其他工具实现单测 2. commitlint/eslint/husky规范化 3. CICD使用github actions,配合qodo实现pr审查等使用ai管理,PockeFlow去生成仓库文档,部署上nextjs及项目要求vercel部署 4. load比较多3D模型的时候性能可能会捉急,如何优化充分利用API请求load返回时间及ssr,tubropack增量更新 5. gsap动画优化,静态资源优化 ## 业务流程 1. 3D生成使用meshy.ai或者其他生成式API去实现 1. API 申请,使用时api轮训还是可供选择自配置 2. API 配置放在哪里,如何保证key的安全不被打野使用 2. 根据prompt去请求API,请求后下载模型展示还是直接展示,等待动画需要美化有趣,返回数据及模型可供用户选择,展示时候需要autoRotate。 3. 选择后请求合约实现链上 4. 部署需要和工程方面耦合 ## 价值 1. 拥有类似nft的个人资产,根据个人画像等资产及prompt喜好生成个性化非同质3D资产 --- ## condev-monitor 项目部署问题 - URL: https://blog.lemonadec.cc/posts/condev-monitor?lang=zh - Date: 2025-01-11 - Language: zh - Type: 文章 首先介绍一下condev-monitor项目,这个项目是用来复刻类似sentry的前端监控系统。主要分为以下几部分,监控错误、性能等的sdk。用于测试安装上述sdk的前端页面项目examples/vanilla项目。通过sdk上报错误的服务端dsn-server。以及用于dashboard展示的前端frontend/monitor以及其后端backend/monitor。 部署方式一开始想使用docker-compose部署在coolify上,尝试多次在部署过程中network被coolify内部prune掉,且出现很多问题,可能是在部署的时候docker-compose中的caddy和coolify服务本身的caddy冲突,尝试多次未果后购买新服务器选用docker-compose部署方案。 项目采用docker-compose部署,整个项目使用了很多镜像。开发环境使用两个数据库clickhosue以及postgres两个dcoker镜像,其余部分在本地pnpm start:dev以及pnpm dev命令执行去本地开发。开发环境下.env由各自项目维护。而线上部署的时候,nextjs项目主流两种部署方式是nixpacks以及docker部署。项目根据自托管需求的时候,nextjs选用可以部署在cloudflare上的adapter方案opennext,后端nestjs可以部署在企业内网主机上,通过tunnel。或者使用docker-compose将前后端都部署在企业内网主机上。两个后端中nestjs不能去掉node_modules去部署,所以后端部署的时候要么在服务器上pm2启动要么把node_modules打进docker中。尝试在服务器上跑pm2的时候,opennext项目也尝试的pm2运行但是出现错误,因此后来选择docker-compose全量部署在服务器上。至此已经踩坑过了coolify以及pm2+docker-compose混合部署的方案。 使用阿里云的2c2g+AliLinux系统作为部署docker镜像及其,遇到OOM总是崩溃,swap配置了但不够用。所以后面打算后端使用pm2,docker化数据库clickhosue以及pg,但是尝试过后部署步骤繁琐故舍弃,转而投入全docker-compose部署。后端dashboard的nestjs项目中使用argon2在阿里云服务器中默认py3.6编译报错崩溃,尝试换py3.7重新编译依然报错。总是会导致这种情况,后面加密依赖部分直接更换bcryptjs了 另一个是在阿里云服务器中使用docker-compose部署的时候,dashboard的nestjs后端项目中使用比较旧的nest-modules/mailer的时候会报错css-in-js的依赖缺失。查看github issues时候有解决方案但是比较不标准导致步骤繁琐。未来维护可能更麻烦,所以换了nodemailer。 总是在阿里云服务器中爆OOM,所以选用了外网的netcup的4c6g机器,避免了麻烦的备案以及docker镜像设置,而且后续开发其他ai项目的时候可以避免openai在中国地区不可用的麻烦(cfworker方案已失效)。使用docker-compose部署全量镜像过程中正常部署,但是在测试过程中发现收发不了邮件。经过测试机器脚本发现服务器不支持smtp发送邮件。所以在之前通过nodemailer通过smtp发送163邮箱的基础上,优先使用resend的http服务发送邮箱,当发送不了http的时候转而使用smtp去发送。这就保证出现严重错误时邮件服务正常运行。 至此,本项目在依赖替换以及部署过程中的错误和坑 ---