From 448aeacd113514d990c38d5f3479d77d1ccf8e6c Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:51:53 +0800 Subject: [PATCH 01/27] Refocus MPV2 around service-led lead generation --- README.md | 19 +++- docs/FrankMoneyPrinter.md | 187 +++++++++++++++++++++++++++++++++++ docs/Roadmap.md | 104 +++++++++++++++++--- src/classes/Twitter.py | 35 ++++++- src/classes/YouTube.py | 202 +++++++++++++++++++++++++++++--------- src/content_profile.py | 111 +++++++++++++++++++++ src/cron.py | 6 +- src/main.py | 88 +++++++++++++++-- 8 files changed, 681 insertions(+), 71 deletions(-) create mode 100644 docs/FrankMoneyPrinter.md create mode 100644 src/content_profile.py diff --git a/README.md b/README.md index 991acd728..629e834d2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # MoneyPrinter V2 +Frank's fork turns MPV2 from a generic faceless-content tool into a client-acquisition engine for service-led AI work: case-study Shorts, cross-platform distribution, and targeted outreach for open-source AI / web deployment, hardening, and customization work. + Sponsored by Post Bridge @@ -15,8 +17,8 @@ Sponsored by Post Bridge [![GitHub stars](https://img.shields.io/github/stars/FujiwaraChoki/MoneyPrinterV2?style=for-the-badge)](https://github.com/FujiwaraChoki/MoneyPrinterV2/stargazers) [![Discord](https://img.shields.io/discord/1134848537704804432?style=for-the-badge)](https://dsc.gg/fuji-community) -An Application that automates the process of making money online. -MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of the MoneyPrinter project. It is a complete rewrite of the original project, with a focus on a wider range of features and a more modular architecture. +An application that automates repetitive parts of online monetization. +MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of the MoneyPrinter project. This fork keeps the modular core, but specializes it around proof-driven marketing for technical services instead of generic traffic farming. > **Note:** MPV2 needs Python 3.12 to function effectively. > Watch the YouTube video [here](https://youtu.be/wAZ_ZSuIqfk) @@ -27,6 +29,19 @@ MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of th - [x] YouTube Shorts Automator (with CRON Jobs => `scheduler`) - [x] Affiliate Marketing (Amazon + Twitter) - [x] Find local businesses & cold outreach +- [x] Service-led content profiles for case-study style YouTube / X accounts +- [x] Cross-post YouTube uploads to TikTok / Instagram via Post Bridge + +## This Fork's Goal + +This fork is optimized for a narrower business model: + +- attract founders, indie hackers, and small teams +- publish technical case-study content instead of generic faceless clips +- turn real delivery work into proof assets +- use outreach to find buyers for deployment, hardening, and customization services + +See [docs/FrankMoneyPrinter.md](docs/FrankMoneyPrinter.md) for the specialization strategy and [docs/Roadmap.md](docs/Roadmap.md) for the implementation phases. ## Versions diff --git a/docs/FrankMoneyPrinter.md b/docs/FrankMoneyPrinter.md new file mode 100644 index 000000000..0cf68cbd5 --- /dev/null +++ b/docs/FrankMoneyPrinter.md @@ -0,0 +1,187 @@ +# Frank's MoneyPrinter + +## What This Fork Is + +This is not a generic "AI makes money online" machine. + +For Frank, this fork is a: + +- proof engine +- content engine +- outreach engine + +It exists to support one concrete service business: + +> Help founders and small teams deploy, harden, and adapt open-source AI / web projects so they become usable in the real world. + +## What This Fork Is Not + +This fork is not optimized for: + +- faceless entertainment channels +- broad affiliate spam +- generic motivational AI content +- waiting for platform ad revenue as the first monetization layer + +Those paths are slower, noisier, and less aligned with Frank's actual strengths. + +## Core Strengths This Fork Must Amplify + +Based on the discovery work, the fork should amplify: + +- extracting precise requirements from messy input +- solving technical problems with AI as a force multiplier +- explaining complex topics clearly +- documenting work so it becomes reusable +- operating with a security-aware mindset + +## Business Thesis + +Frank is currently strongest as: + +> An AI-assisted delivery-focused problem solver. + +Near-term positioning: + +> Open-source AI / web project deployment, hardening, and customization. + +This is stronger than vague labels like "website developer" or "consultant" because it: + +- maps to real evidence +- is easier to explain +- is easier to price +- creates better case-study content + +## Offer Ladder + +### 1. Deployment Sprint + +Best for: + +- customers who picked a GitHub project but cannot get it running + +Output: + +- local or server deployment +- environment setup +- domain / HTTPS / basic launch notes + +### 2. Hardening Pass + +Best for: + +- projects that run but are fragile, overexposed, or badly configured + +Output: + +- basic hardening review +- auth / env / proxy / backup suggestions +- concrete risk notes + +### 3. Customization Sprint + +Best for: + +- buyers who do not want a greenfield build +- buyers who want an existing project adapted to their real workflow + +Output: + +- scoped changes on top of an existing codebase +- UI / workflow / integration adjustments + +## Content Strategy + +Content is not the business model. + +Content is evidence that Frank can: + +- make complex systems work +- avoid naive mistakes +- turn vague requirements into practical outcomes + +### Content Pillars + +- deployment lessons +- hardening and risk reduction +- open-source project teardowns +- workflow adaptation and customization +- calm technical judgment for non-expert buyers + +### Short-Form Content Pattern + +Every short should follow one of these angles: + +- what usually breaks +- what most people miss +- how to deploy this properly +- how to reduce one expensive risk +- how to adapt an existing project to a real use case + +### Tone + +- calm +- specific +- operator-like +- no fake hustle energy +- no empty AI hot takes + +## Outreach Strategy + +Outreach should target: + +- indie hackers +- small SaaS teams +- operators with visible tooling pain +- buyers already trying to use open-source tools + +Outreach should not say: + +- "I can do anything" +- "I am an AI expert" +- "I offer consulting" + +Outreach should say: + +- I can help you get this running +- I can harden this setup +- I can adapt this project to your workflow + +## Product Direction + +This fork should move through these layers in order: + +1. paid delivery +2. public proof +3. repeatable templates +4. productized services +5. selective digital products / affiliate later + +If a future idea skips layer 1 and layer 2, it is probably premature for this fork. + +## Public Fork Lessons + +Publicly visible evolution around MoneyPrinter-like tools points in a few directions: + +- stronger localization +- web UI and easier setup +- better TTS / subtitles / media quality +- multi-platform distribution +- more robust automation surfaces + +Frank's fork intentionally takes a different angle: + +- less generic media volume +- more business relevance +- more proof from real delivery work +- better alignment with service revenue + +## Operational Rules + +Before building anything new in this repo, ask: + +1. Does it help attract or convert the right client? +2. Does it help turn real work into reusable proof? +3. Does it reduce delivery time on repeated service work? + +If not, it is probably distraction, not leverage. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 2796e3e4a..031847edf 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -1,18 +1,100 @@ -# MPV2 Roadmap +# Frank MoneyPrinter Roadmap -This document outlines the features that need to be implemented in MPV2. +This roadmap keeps the fork aligned with one business objective: -## Features +> Turn real open-source AI / web delivery work into proof-driven content, targeted outreach, and paid service revenue. -- [ ] Automated Cold Calling -- [ ] Item Flipping (such as sneakers) -- [ ] Create a Short based on long-form content -- [ ] Subtitles for Shorts +The default upstream "faceless content at scale" path is not the primary strategy for this fork. -## Adding a new feature +## Positioning -If you want to add a new feature to MPV2, please create a new issue and label it with `enhancement`. After that, create a new branch and start working on the feature. Once you are done, create a pull request and assign it to the issue you created earlier. +Primary role: -## Contributing +- Open-source AI / web project deployment +- Basic hardening and risk reduction +- Business-facing customization on top of existing projects -Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. \ No newline at end of file +Primary audience: + +- Indie hackers +- Solo founders +- Small product teams +- Buyers who have already picked a GitHub project but need it running + +Primary monetization order: + +1. Deployment / hardening / customization services +2. Content as proof and lead generation +3. Outreach to accelerate conversations +4. Affiliate / info product / productized templates later + +## Phase 1: Proof-Driven Messaging + +- [x] Replace generic fork positioning in the README +- [x] Define the fork's specialized business thesis +- [x] Add a dedicated strategy document for Frank's version +- [x] Add a roadmap that prevents future drift +- [ ] Write the final service-page copy for `fzhang.dev` +- [ ] Pick one public offer as the single CTA for all channels + +## Phase 2: Content Engine Refactor + +- [x] Add account-level service content profiles +- [x] Make YouTube topic generation case-study oriented +- [x] Make YouTube scripts attract qualified prospects instead of generic viewers +- [x] Make metadata and descriptions include soft service CTAs +- [x] Make X posts calm, practical, and problem-solution driven +- [ ] Add support for loading reusable case briefs from files +- [ ] Add a review step before publishing generated content +- [ ] Add content variants for `deployment`, `hardening`, and `customization` + +## Phase 3: Offer Packaging + +- [ ] Define 3 standard offers: +- [ ] `Deployment Sprint` +- [ ] `Hardening Pass` +- [ ] `Customization Sprint` +- [ ] Document delivery boundaries, inputs, outputs, and exclusions +- [ ] Add pricing guidance and upgrade path +- [ ] Add templates for discovery notes and project handoff notes + +## Phase 4: Outreach Engine + +- [ ] Rewrite outreach copy around concrete technical outcomes +- [ ] Narrow scraping keywords toward founder / operator / builder intent +- [ ] Add contact qualification notes before sending outreach +- [ ] Track reply quality, booked calls, and converted deals +- [ ] Build one outreach flow per offer instead of generic cold email + +## Phase 5: Proof Asset Library + +- [ ] Publish 3 public case studies +- [ ] Publish 10 short-form technical proof posts +- [ ] Publish 3 longer articles on `fzhang.dev` +- [ ] Build a reusable before/after screenshot library +- [ ] Maintain a list of real problems solved, grouped by offer + +## Phase 6: Productization + +- [ ] Turn repeatable deployment patterns into checklists +- [ ] Turn hardening steps into reusable audits +- [ ] Turn recurring setup work into packaged templates +- [ ] Evaluate a paid knowledge product or starter kit +- [ ] Evaluate selective affiliate recommendations only after proof exists + +## Decision Filters + +Before adding any new feature, ask: + +1. Does this make it easier to win deployment / hardening / customization clients? +2. Does this create public proof of real technical work? +3. Does this reduce delivery friction or improve reuse? +4. If the answer is "no", it is probably off-strategy for this fork. + +## Immediate Next Tasks + +- [ ] Create one YouTube account and one X account using the new service-led profile fields +- [ ] Define a single target customer and one offer name +- [ ] Create 3 content angles from real delivery experience +- [ ] Publish one short, one X post, and one site article from the same proof asset +- [ ] Update `origin` / `upstream` remotes so this fork can be pushed cleanly diff --git a/src/classes/Twitter.py b/src/classes/Twitter.py index 605a59a65..69a384e04 100644 --- a/src/classes/Twitter.py +++ b/src/classes/Twitter.py @@ -8,6 +8,7 @@ from config import * from status import * from llm_provider import generate_text +from content_profile import build_profile_context, has_service_strategy, normalize_content_profile from typing import List, Optional from datetime import datetime from termcolor import colored @@ -27,7 +28,12 @@ class Twitter: """ def __init__( - self, account_uuid: str, account_nickname: str, fp_profile_path: str, topic: str + self, + account_uuid: str, + account_nickname: str, + fp_profile_path: str, + topic: str, + content_profile: dict | None = None, ) -> None: """ Initializes the Twitter Bot. @@ -44,6 +50,7 @@ def __init__( self.account_nickname: str = account_nickname self.fp_profile_path: str = fp_profile_path self.topic: str = topic + self.content_profile = normalize_content_profile(content_profile) # Initialize the Firefox profile self.options: Options = Options() @@ -202,10 +209,28 @@ def generate_post(self) -> str: Returns: post (str): The post """ - completion = generate_text( - f"Generate a Twitter post about: {self.topic} in {get_twitter_language()}. " - "The Limit is 2 sentences. Choose a specific sub-topic of the provided topic." - ) + if has_service_strategy(self.content_profile): + completion = generate_text( + f""" + Write a concise X post in {get_twitter_language()} for a technical service business. + + Topic / angle: {self.topic} + {build_profile_context(self.content_profile)} + + Requirements: + - Maximum 240 characters + - Sound like a calm operator, not a hype marketer + - Mention one concrete problem, one practical insight, and optionally a soft CTA + - Prefer deployment, security, workflow, or implementation lessons + - Avoid generic inspiration and vague AI hot takes + - Only return the post text + """ + ) + else: + completion = generate_text( + f"Generate a Twitter post about: {self.topic} in {get_twitter_language()}. " + "The Limit is 2 sentences. Choose a specific sub-topic of the provided topic." + ) if get_verbose(): info("Generating a post...") diff --git a/src/classes/YouTube.py b/src/classes/YouTube.py index 79640f661..be5df3ab1 100644 --- a/src/classes/YouTube.py +++ b/src/classes/YouTube.py @@ -13,6 +13,7 @@ from config import * from status import * from uuid import uuid4 +from content_profile import build_profile_context, has_service_strategy, normalize_content_profile from constants import * from typing import List from moviepy.editor import * @@ -54,6 +55,7 @@ def __init__( fp_profile_path: str, niche: str, language: str, + content_profile: dict | None = None, ) -> None: """ Constructor for YouTube Class. @@ -73,6 +75,7 @@ def __init__( self._fp_profile_path: str = fp_profile_path self._niche: str = niche self._language: str = language + self.content_profile = normalize_content_profile(content_profile) self.images = [] @@ -138,9 +141,29 @@ def generate_topic(self) -> str: Returns: topic (str): The generated topic. """ - completion = self.generate_response( - f"Please generate a specific video idea that takes about the following topic: {self.niche}. Make it exactly one sentence. Only return the topic, nothing else." - ) + if has_service_strategy(self.content_profile): + completion = self.generate_response( + f""" + You are planning a short-form educational video that attracts qualified leads to a technical service. + + Domain / niche: {self.niche} + Language: {self.language} + {build_profile_context(self.content_profile)} + + Generate one concrete short-video angle in exactly one sentence. + + Requirements: + - Make it practical, credibility-first, and case-study oriented. + - Prefer deployment lessons, security pitfalls, implementation trade-offs, or client-facing outcomes. + - Avoid vague motivation, generic AI news, and broad listicles. + - The angle should feel like something a founder or small team would actually click because it solves a real problem. + - Only return the topic sentence. + """ + ) + else: + completion = self.generate_response( + f"Please generate a specific video idea that takes about the following topic: {self.niche}. Make it exactly one sentence. Only return the topic, nothing else." + ) if not completion: error("Failed to generate Topic.") @@ -157,28 +180,55 @@ def generate_script(self) -> str: script (str): The script of the video. """ sentence_length = get_script_sentence_length() - prompt = f""" - Generate a script for a video in {sentence_length} sentences, depending on the subject of the video. + if has_service_strategy(self.content_profile): + prompt = f""" + Write a short-form video script in {sentence_length} short sentences. + + Subject: {self.subject} + Language: {self.language} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + + Script goals: + - Attract the right prospect, not broad entertainment traffic. + - Sound like a calm technical operator explaining a real-world lesson. + - Make the audience feel "this person can probably solve my problem". + + Structure: + - Sentence 1: Name a concrete problem, failure mode, or costly mistake. + - Sentence 2: Explain why it happens or what most people miss. + - Sentence 3: Show the practical fix, principle, or workflow. + - Sentence 4: Describe the business/technical outcome or a soft CTA. + + Rules: + - No markdown, no title, no bullet points. + - No hype, no empty inspiration, no "welcome back". + - Do not mention the prompt or the sentence count. + - Only return the raw script. + """ + else: + prompt = f""" + Generate a script for a video in {sentence_length} sentences, depending on the subject of the video. - The script is to be returned as a string with the specified number of paragraphs. + The script is to be returned as a string with the specified number of paragraphs. - Here is an example of a string: - "This is an example string." + Here is an example of a string: + "This is an example string." - Do not under any circumstance reference this prompt in your response. + Do not under any circumstance reference this prompt in your response. - Get straight to the point, don't start with unnecessary things like, "welcome to this video". + Get straight to the point, don't start with unnecessary things like, "welcome to this video". - Obviously, the script should be related to the subject of the video. - - YOU MUST NOT EXCEED THE {sentence_length} SENTENCES LIMIT. MAKE SURE THE {sentence_length} SENTENCES ARE SHORT. - YOU MUST NOT INCLUDE ANY TYPE OF MARKDOWN OR FORMATTING IN THE SCRIPT, NEVER USE A TITLE. - YOU MUST WRITE THE SCRIPT IN THE LANGUAGE SPECIFIED IN [LANGUAGE]. - ONLY RETURN THE RAW CONTENT OF THE SCRIPT. DO NOT INCLUDE "VOICEOVER", "NARRATOR" OR SIMILAR INDICATORS OF WHAT SHOULD BE SPOKEN AT THE BEGINNING OF EACH PARAGRAPH OR LINE. YOU MUST NOT MENTION THE PROMPT, OR ANYTHING ABOUT THE SCRIPT ITSELF. ALSO, NEVER TALK ABOUT THE AMOUNT OF PARAGRAPHS OR LINES. JUST WRITE THE SCRIPT - - Subject: {self.subject} - Language: {self.language} - """ + Obviously, the script should be related to the subject of the video. + + YOU MUST NOT EXCEED THE {sentence_length} SENTENCES LIMIT. MAKE SURE THE {sentence_length} SENTENCES ARE SHORT. + YOU MUST NOT INCLUDE ANY TYPE OF MARKDOWN OR FORMATTING IN THE SCRIPT, NEVER USE A TITLE. + YOU MUST WRITE THE SCRIPT IN THE LANGUAGE SPECIFIED IN [LANGUAGE]. + ONLY RETURN THE RAW CONTENT OF THE SCRIPT. DO NOT INCLUDE "VOICEOVER", "NARRATOR" OR SIMILAR INDICATORS OF WHAT SHOULD BE SPOKEN AT THE BEGINNING OF EACH PARAGRAPH OR LINE. YOU MUST NOT MENTION THE PROMPT, OR ANYTHING ABOUT THE SCRIPT ITSELF. ALSO, NEVER TALK ABOUT THE AMOUNT OF PARAGRAPHS OR LINES. JUST WRITE THE SCRIPT + + Subject: {self.subject} + Language: {self.language} + """ completion = self.generate_response(prompt) # Apply regex to remove * @@ -204,18 +254,56 @@ def generate_metadata(self) -> dict: Returns: metadata (dict): The generated metadata. """ - title = self.generate_response( - f"Please generate a YouTube Video Title for the following subject, including hashtags: {self.subject}. Only return the title, nothing else. Limit the title under 100 characters." - ) + if has_service_strategy(self.content_profile): + title = self.generate_response( + f""" + Generate a YouTube Shorts title for this technical service-led video. + + Subject: {self.subject} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + + Requirements: + - Under 90 characters + - Specific and useful, not clickbait + - May use 1-2 targeted hashtags if they help + - Should signal a real deployment, security, automation, or implementation lesson + - Only return the title + """ + ) + else: + title = self.generate_response( + f"Please generate a YouTube Video Title for the following subject, including hashtags: {self.subject}. Only return the title, nothing else. Limit the title under 100 characters." + ) if len(title) > 100: if get_verbose(): warning("Generated Title is too long. Retrying...") return self.generate_metadata() - description = self.generate_response( - f"Please generate a YouTube Video Description for the following script: {self.script}. Only return the description, nothing else." - ) + if has_service_strategy(self.content_profile): + description = self.generate_response( + f""" + Generate a concise YouTube video description for a technical case-study short. + + Subject: {self.subject} + Script: {self.script} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + + Requirements: + - Summarize the lesson in 2-4 short lines + - Sound practical and trustworthy + - Mention the target outcome for the audience + - Include a soft CTA to contact or learn more + - If a CTA URL is present in the context, include it naturally + - Only return the description + """ + ) + else: + description = self.generate_response( + f"Please generate a YouTube Video Description for the following script: {self.script}. Only return the description, nothing else." + ) self.metadata = {"title": title, "description": description} @@ -230,31 +318,55 @@ def generate_prompts(self) -> List[str]: """ n_prompts = len(self.script) / 3 - prompt = f""" - Generate {n_prompts} Image Prompts for AI Image Generation, - depending on the subject of a video. - Subject: {self.subject} + if has_service_strategy(self.content_profile): + prompt = f""" + Generate {int(n_prompts)} vertical image prompts for an AI-generated technical case-study short. + + Subject: {self.subject} + Script: {self.script} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + + Visual direction: + - product UI mockups + - terminal / dashboard / architecture visuals + - secure infrastructure scenes + - founder workflow, deployment workflow, before/after states + - realistic modern SaaS or engineering imagery + + Rules: + - Return a JSON array of strings only + - Each prompt should be a full sentence + - Keep prompts grounded, professional, and visually coherent + - Avoid fantasy art, surrealism, and generic motivational imagery + - Do not repeat the script verbatim + """ + else: + prompt = f""" + Generate {n_prompts} Image Prompts for AI Image Generation, + depending on the subject of a video. + Subject: {self.subject} - The image prompts are to be returned as - a JSON-Array of strings. + The image prompts are to be returned as + a JSON-Array of strings. - Each search term should consist of a full sentence, - always add the main subject of the video. + Each search term should consist of a full sentence, + always add the main subject of the video. - Be emotional and use interesting adjectives to make the - Image Prompt as detailed as possible. + Be emotional and use interesting adjectives to make the + Image Prompt as detailed as possible. - YOU MUST ONLY RETURN THE JSON-ARRAY OF STRINGS. - YOU MUST NOT RETURN ANYTHING ELSE. - YOU MUST NOT RETURN THE SCRIPT. + YOU MUST ONLY RETURN THE JSON-ARRAY OF STRINGS. + YOU MUST NOT RETURN ANYTHING ELSE. + YOU MUST NOT RETURN THE SCRIPT. - The search terms must be related to the subject of the video. - Here is an example of a JSON-Array of strings: - ["image prompt 1", "image prompt 2", "image prompt 3"] + The search terms must be related to the subject of the video. + Here is an example of a JSON-Array of strings: + ["image prompt 1", "image prompt 2", "image prompt 3"] - For context, here is the full text: - {self.script} - """ + For context, here is the full text: + {self.script} + """ completion = ( str(self.generate_response(prompt)) diff --git a/src/content_profile.py b/src/content_profile.py new file mode 100644 index 000000000..946f25c19 --- /dev/null +++ b/src/content_profile.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from typing import Any + + +def _split_items(value: Any) -> list[str]: + """ + Normalizes comma/newline separated values into a compact string list. + + Args: + value (Any): Raw user-provided value + + Returns: + items (list[str]): Cleaned list of strings + """ + if value is None: + return [] + + if isinstance(value, list): + return [str(item).strip() for item in value if str(item).strip()] + + if not isinstance(value, str): + return [str(value).strip()] if str(value).strip() else [] + + normalized = value.replace("\n", ",") + return [item.strip() for item in normalized.split(",") if item.strip()] + + +def normalize_content_profile(content_profile: dict | None) -> dict: + """ + Returns a normalized content profile used by service-led content prompts. + + Args: + content_profile (dict | None): Raw profile data from the account cache + + Returns: + profile (dict): Normalized profile + """ + raw = content_profile or {} + + profile = { + "content_mode": str(raw.get("content_mode", "") or "").strip().lower(), + "target_customer": str(raw.get("target_customer", "") or "").strip(), + "offer_name": str(raw.get("offer_name", "") or "").strip(), + "primary_problem": str(raw.get("primary_problem", "") or "").strip(), + "desired_outcome": str(raw.get("desired_outcome", "") or "").strip(), + "cta_url": str(raw.get("cta_url", "") or "").strip(), + "proof_points": _split_items(raw.get("proof_points")), + "content_pillars": _split_items(raw.get("content_pillars")), + } + + if not profile["content_mode"]: + has_strategy_data = any( + [ + profile["target_customer"], + profile["offer_name"], + profile["primary_problem"], + profile["desired_outcome"], + profile["cta_url"], + profile["proof_points"], + profile["content_pillars"], + ] + ) + profile["content_mode"] = "service_case_study" if has_strategy_data else "legacy" + + return profile + + +def has_service_strategy(content_profile: dict | None) -> bool: + """ + Determines whether an account should use the personalized service-led prompts. + + Args: + content_profile (dict | None): Account content profile + + Returns: + enabled (bool): True when service-led prompts should be used + """ + profile = normalize_content_profile(content_profile) + return profile["content_mode"] == "service_case_study" + + +def build_profile_context(content_profile: dict | None) -> str: + """ + Serializes the normalized profile into prompt-friendly bullet points. + + Args: + content_profile (dict | None): Account content profile + + Returns: + context (str): Compact text block + """ + profile = normalize_content_profile(content_profile) + + lines = [] + if profile["target_customer"]: + lines.append(f"Target customer: {profile['target_customer']}") + if profile["offer_name"]: + lines.append(f"Offer: {profile['offer_name']}") + if profile["primary_problem"]: + lines.append(f"Primary problem solved: {profile['primary_problem']}") + if profile["desired_outcome"]: + lines.append(f"Desired customer outcome: {profile['desired_outcome']}") + if profile["proof_points"]: + lines.append("Proof points: " + "; ".join(profile["proof_points"])) + if profile["content_pillars"]: + lines.append("Content pillars: " + "; ".join(profile["content_pillars"])) + if profile["cta_url"]: + lines.append(f"CTA URL: {profile['cta_url']}") + + return "\n".join(lines) diff --git a/src/cron.py b/src/cron.py index 9d002dc73..bb461636c 100644 --- a/src/cron.py +++ b/src/cron.py @@ -54,7 +54,8 @@ def main(): acc["id"], acc["nickname"], acc["firefox_profile"], - acc["topic"] + acc["topic"], + acc.get("content_profile"), ) twitter.post() if verbose: @@ -77,7 +78,8 @@ def main(): acc["nickname"], acc["firefox_profile"], acc["niche"], - acc["language"] + acc["language"], + acc.get("content_profile"), ) youtube.generate_video(tts) upload_success = youtube.upload_video() diff --git a/src/main.py b/src/main.py index 8bb1542b3..6ce65f6a3 100644 --- a/src/main.py +++ b/src/main.py @@ -18,6 +18,57 @@ from llm_provider import list_models, select_model, get_active_model from post_bridge_integration import maybe_crosspost_youtube_short + +def prompt_content_profile(default_topic: str, account_type: str) -> dict: + """ + Collects optional service-led content settings for an account. + + Args: + default_topic (str): Fallback niche/topic for the account + account_type (str): Human-readable account type label + + Returns: + profile (dict): Content profile stored in the account cache + """ + info( + "\nOptional: configure a service-led content profile for this account.", + False, + ) + use_strategy = question( + " => Use personalized case-study content prompts? (Yes/No, default Yes): " + ).strip().lower() + + if use_strategy in {"no", "n"}: + return {"content_mode": "legacy"} + + target_customer = question( + " => Target customer (e.g. indie hackers, founders, small teams): " + ).strip() + offer_name = question( + f" => Main offer promoted by this {account_type} account: " + ).strip() + primary_problem = question(" => Main problem you solve for them: ").strip() + desired_outcome = question(" => Desired customer outcome: ").strip() + cta_url = question(" => CTA URL (optional): ").strip() + proof_points = question( + " => Proof points, comma-separated (optional): " + ).strip() + content_pillars = question( + f" => Content pillars for '{default_topic}', comma-separated (optional): " + ).strip() + + return { + "content_mode": "service_case_study", + "target_customer": target_customer, + "offer_name": offer_name, + "primary_problem": primary_problem, + "desired_outcome": desired_outcome, + "cta_url": cta_url, + "proof_points": proof_points, + "content_pillars": content_pillars, + } + + def main(): """Main entry point for the application, providing a menu-driven interface to manage YouTube, Twitter bots, Affiliate Marketing, and Outreach tasks. @@ -82,6 +133,7 @@ def main(): fp_profile = question(" => Enter the path to the Firefox profile: ") niche = question(" => Enter the account niche: ") language = question(" => Enter the account language: ") + content_profile = prompt_content_profile(niche, "YouTube") account_data = { "id": generated_uuid, @@ -89,6 +141,7 @@ def main(): "firefox_profile": fp_profile, "niche": niche, "language": language, + "content_profile": content_profile, "videos": [], } @@ -97,10 +150,17 @@ def main(): success("Account configured successfully!") else: table = PrettyTable() - table.field_names = ["ID", "UUID", "Nickname", "Niche"] + table.field_names = ["ID", "UUID", "Nickname", "Niche", "Offer"] for account in cached_accounts: - table.add_row([cached_accounts.index(account) + 1, colored(account["id"], "cyan"), colored(account["nickname"], "blue"), colored(account["niche"], "green")]) + offer_name = account.get("content_profile", {}).get("offer_name", "") + table.add_row([ + cached_accounts.index(account) + 1, + colored(account["id"], "cyan"), + colored(account["nickname"], "blue"), + colored(account["niche"], "green"), + colored((offer_name or "-")[:32], "yellow"), + ]) print(table) info("Type 'd' to delete an account.", False) @@ -144,7 +204,8 @@ def main(): selected_account["nickname"], selected_account["firefox_profile"], selected_account["niche"], - selected_account["language"] + selected_account["language"], + selected_account.get("content_profile"), ) while True: @@ -238,20 +299,29 @@ def job(): nickname = question(" => Enter a nickname for this account: ") fp_profile = question(" => Enter the path to the Firefox profile: ") topic = question(" => Enter the account topic: ") + content_profile = prompt_content_profile(topic, "Twitter / X") add_account("twitter", { "id": generated_uuid, "nickname": nickname, "firefox_profile": fp_profile, "topic": topic, + "content_profile": content_profile, "posts": [] }) else: table = PrettyTable() - table.field_names = ["ID", "UUID", "Nickname", "Account Topic"] + table.field_names = ["ID", "UUID", "Nickname", "Account Topic", "Offer"] for account in cached_accounts: - table.add_row([cached_accounts.index(account) + 1, colored(account["id"], "cyan"), colored(account["nickname"], "blue"), colored(account["topic"], "green")]) + offer_name = account.get("content_profile", {}).get("offer_name", "") + table.add_row([ + cached_accounts.index(account) + 1, + colored(account["id"], "cyan"), + colored(account["nickname"], "blue"), + colored(account["topic"], "green"), + colored((offer_name or "-")[:32], "yellow"), + ]) print(table) info("Type 'd' to delete an account.", False) @@ -290,7 +360,13 @@ def job(): error("Invalid account selected. Please try again.", "red") main() else: - twitter = Twitter(selected_account["id"], selected_account["nickname"], selected_account["firefox_profile"], selected_account["topic"]) + twitter = Twitter( + selected_account["id"], + selected_account["nickname"], + selected_account["firefox_profile"], + selected_account["topic"], + selected_account.get("content_profile"), + ) while True: From 2d605f557fd3a4d618691ecafdc76b0d275ab2db Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:04:52 +0800 Subject: [PATCH 02/27] Add reusable case briefs and content review --- docs/CaseBriefTemplate.md | 34 ++++++++++++ docs/Roadmap.md | 4 +- src/classes/Twitter.py | 48 ++++++++++++++++- src/classes/YouTube.py | 109 +++++++++++++++++++++++++++++++++++++- src/content_profile.py | 53 ++++++++++++++++++ src/main.py | 8 +++ 6 files changed, 251 insertions(+), 5 deletions(-) create mode 100644 docs/CaseBriefTemplate.md diff --git a/docs/CaseBriefTemplate.md b/docs/CaseBriefTemplate.md new file mode 100644 index 000000000..e8995806b --- /dev/null +++ b/docs/CaseBriefTemplate.md @@ -0,0 +1,34 @@ +# Case Brief Template + +Use one file like this per repeatable content angle or client-safe case study. + +```md +# Case Brief + +## Context +- Project: +- Customer type: +- Starting situation: + +## Problem +- What was broken, risky, or blocked? +- What did most people miss? + +## Work Performed +- Deployment steps: +- Hardening steps: +- Customization steps: + +## Outcome +- What changed? +- What business or technical result mattered? + +## Safe-To-Publish Notes +- What details must stay generic? +- Which tool / stack names are safe to mention? + +## CTA Direction +- Which offer should this case study lead into? +``` + +Then store the file anywhere inside the repo and reference its relative path when creating a YouTube or X account. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 031847edf..6a5a6ac3d 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -44,8 +44,8 @@ Primary monetization order: - [x] Make YouTube scripts attract qualified prospects instead of generic viewers - [x] Make metadata and descriptions include soft service CTAs - [x] Make X posts calm, practical, and problem-solution driven -- [ ] Add support for loading reusable case briefs from files -- [ ] Add a review step before publishing generated content +- [x] Add support for loading reusable case briefs from files +- [x] Add a review step before publishing generated content - [ ] Add content variants for `deployment`, `hardening`, and `customization` ## Phase 3: Offer Packaging diff --git a/src/classes/Twitter.py b/src/classes/Twitter.py index 69a384e04..a249ebf5a 100644 --- a/src/classes/Twitter.py +++ b/src/classes/Twitter.py @@ -8,7 +8,12 @@ from config import * from status import * from llm_provider import generate_text -from content_profile import build_profile_context, has_service_strategy, normalize_content_profile +from content_profile import ( + build_profile_context, + has_service_strategy, + load_case_brief, + normalize_content_profile, +) from typing import List, Optional from datetime import datetime from termcolor import colored @@ -51,6 +56,7 @@ def __init__( self.fp_profile_path: str = fp_profile_path self.topic: str = topic self.content_profile = normalize_content_profile(content_profile) + self.case_brief = load_case_brief(self.content_profile) # Initialize the Firefox profile self.options: Options = Options() @@ -216,6 +222,8 @@ def generate_post(self) -> str: Topic / angle: {self.topic} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Requirements: - Maximum 240 characters @@ -242,9 +250,47 @@ def generate_post(self) -> str: # Apply Regex to remove all * completion = re.sub(r"\*", "", completion).replace('"', "") + if has_service_strategy(self.content_profile): + completion = self.review_post(completion) + if get_verbose(): info(f"Length of post: {len(completion)}") if len(completion) >= 260: return completion[:257].rsplit(" ", 1)[0] + "..." return completion + + def review_post(self, draft: str) -> str: + """ + Reviews the generated post against service-led quality constraints. + + Args: + draft (str): Initial generated post + + Returns: + post (str): Reviewed post + """ + reviewed = generate_text( + f""" + Review and improve this X post for a technical service operator. + + Draft: + {draft} + + Context: + Topic / angle: {self.topic} + {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} + + Requirements: + - Keep the core meaning + - Remove hype, fluff, and generic AI phrasing + - Make it sound specific, credible, and useful + - Keep it under 240 characters + - Only return the final post + """ + ) + + cleaned = re.sub(r"\*", "", reviewed).replace('"', "").strip() + return cleaned or draft diff --git a/src/classes/YouTube.py b/src/classes/YouTube.py index be5df3ab1..8ea567c2c 100644 --- a/src/classes/YouTube.py +++ b/src/classes/YouTube.py @@ -13,7 +13,12 @@ from config import * from status import * from uuid import uuid4 -from content_profile import build_profile_context, has_service_strategy, normalize_content_profile +from content_profile import ( + build_profile_context, + has_service_strategy, + load_case_brief, + normalize_content_profile, +) from constants import * from typing import List from moviepy.editor import * @@ -76,6 +81,7 @@ def __init__( self._niche: str = niche self._language: str = language self.content_profile = normalize_content_profile(content_profile) + self.case_brief = load_case_brief(self.content_profile) self.images = [] @@ -149,6 +155,8 @@ def generate_topic(self) -> str: Domain / niche: {self.niche} Language: {self.language} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Generate one concrete short-video angle in exactly one sentence. @@ -188,6 +196,8 @@ def generate_script(self) -> str: Language: {self.language} Domain / niche: {self.niche} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Script goals: - Attract the right prospect, not broad entertainment traffic. @@ -245,7 +255,10 @@ def generate_script(self) -> str: self.script = completion - return completion + if has_service_strategy(self.content_profile): + self.script = self.review_script(self.script) + + return self.script def generate_metadata(self) -> dict: """ @@ -262,6 +275,8 @@ def generate_metadata(self) -> dict: Subject: {self.subject} Domain / niche: {self.niche} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Requirements: - Under 90 characters @@ -290,6 +305,8 @@ def generate_metadata(self) -> dict: Script: {self.script} Domain / niche: {self.niche} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Requirements: - Summarize the lesson in 2-4 short lines @@ -307,6 +324,9 @@ def generate_metadata(self) -> dict: self.metadata = {"title": title, "description": description} + if has_service_strategy(self.content_profile): + self.metadata = self.review_metadata(self.metadata) + return self.metadata def generate_prompts(self) -> List[str]: @@ -326,6 +346,8 @@ def generate_prompts(self) -> List[str]: Script: {self.script} Domain / niche: {self.niche} {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} Visual direction: - product UI mockups @@ -406,6 +428,89 @@ def generate_prompts(self) -> List[str]: return image_prompts + def review_script(self, draft: str) -> str: + """ + Reviews a generated script before publishing. + + Args: + draft (str): Initial script + + Returns: + script (str): Reviewed script + """ + reviewed = self.generate_response( + f""" + Review and improve this short-form technical service script. + + Draft: + {draft} + + Context: + Subject: {self.subject} + Language: {self.language} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} + + Requirements: + - Keep it concise and practical + - Remove hype, filler, and vague wording + - Keep the tone calm and operator-like + - Make the value to the prospect obvious + - Only return the final script + """ + ) + + cleaned = re.sub(r"\*", "", reviewed).strip() + return cleaned or draft + + def review_metadata(self, draft_metadata: dict) -> dict: + """ + Reviews title and description before publishing. + + Args: + draft_metadata (dict): Draft metadata + + Returns: + metadata (dict): Reviewed metadata + """ + reviewed = self.generate_response( + f""" + Review this YouTube Shorts metadata for a technical service-led video. + + Draft title: {draft_metadata.get("title", "")} + Draft description: {draft_metadata.get("description", "")} + + Context: + Subject: {self.subject} + Domain / niche: {self.niche} + {build_profile_context(self.content_profile)} + Reusable case brief: + {self.case_brief or "None"} + + Return valid JSON only with this schema: + {{ + "title": "reviewed title", + "description": "reviewed description" + }} + + Requirements: + - Specific, credible, no hype + - Keep title under 90 characters + - Keep description concise and CTA-aware + """ + ) + + cleaned = reviewed.replace("```json", "").replace("```", "").strip() + try: + parsed = json.loads(cleaned) + title = str(parsed.get("title", "")).strip() or draft_metadata.get("title", "") + description = str(parsed.get("description", "")).strip() or draft_metadata.get("description", "") + return {"title": title, "description": description} + except Exception: + return draft_metadata + def _persist_image(self, image_bytes: bytes, provider_label: str) -> str: """ Writes generated image bytes to a PNG file in .mp. diff --git a/src/content_profile.py b/src/content_profile.py index 946f25c19..901986424 100644 --- a/src/content_profile.py +++ b/src/content_profile.py @@ -1,7 +1,11 @@ from __future__ import annotations +import os + from typing import Any +from config import ROOT_DIR + def _split_items(value: Any) -> list[str]: """ @@ -45,6 +49,8 @@ def normalize_content_profile(content_profile: dict | None) -> dict: "primary_problem": str(raw.get("primary_problem", "") or "").strip(), "desired_outcome": str(raw.get("desired_outcome", "") or "").strip(), "cta_url": str(raw.get("cta_url", "") or "").strip(), + "case_brief_file": str(raw.get("case_brief_file", "") or "").strip(), + "review_notes": str(raw.get("review_notes", "") or "").strip(), "proof_points": _split_items(raw.get("proof_points")), "content_pillars": _split_items(raw.get("content_pillars")), } @@ -57,6 +63,8 @@ def normalize_content_profile(content_profile: dict | None) -> dict: profile["primary_problem"], profile["desired_outcome"], profile["cta_url"], + profile["case_brief_file"], + profile["review_notes"], profile["proof_points"], profile["content_pillars"], ] @@ -107,5 +115,50 @@ def build_profile_context(content_profile: dict | None) -> str: lines.append("Content pillars: " + "; ".join(profile["content_pillars"])) if profile["cta_url"]: lines.append(f"CTA URL: {profile['cta_url']}") + if profile["case_brief_file"]: + lines.append(f"Case brief file: {profile['case_brief_file']}") + if profile["review_notes"]: + lines.append(f"Review notes: {profile['review_notes']}") return "\n".join(lines) + + +def resolve_case_brief_path(content_profile: dict | None) -> str: + """ + Resolves an optional case brief file path relative to the repo root. + + Args: + content_profile (dict | None): Account content profile + + Returns: + path (str): Absolute case brief path or empty string + """ + profile = normalize_content_profile(content_profile) + raw_path = profile["case_brief_file"] + + if not raw_path: + return "" + + if os.path.isabs(raw_path): + return raw_path + + return os.path.join(ROOT_DIR, raw_path) + + +def load_case_brief(content_profile: dict | None) -> str: + """ + Loads an optional reusable case brief from disk. + + Args: + content_profile (dict | None): Account content profile + + Returns: + brief (str): Case brief text or empty string + """ + resolved = resolve_case_brief_path(content_profile) + + if not resolved or not os.path.exists(resolved): + return "" + + with open(resolved, "r", errors="ignore") as handle: + return handle.read().strip() diff --git a/src/main.py b/src/main.py index 6ce65f6a3..f8ec07616 100644 --- a/src/main.py +++ b/src/main.py @@ -50,12 +50,18 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: primary_problem = question(" => Main problem you solve for them: ").strip() desired_outcome = question(" => Desired customer outcome: ").strip() cta_url = question(" => CTA URL (optional): ").strip() + case_brief_file = question( + " => Case brief file path relative to repo (optional): " + ).strip() proof_points = question( " => Proof points, comma-separated (optional): " ).strip() content_pillars = question( f" => Content pillars for '{default_topic}', comma-separated (optional): " ).strip() + review_notes = question( + " => Review notes / guardrails for generated content (optional): " + ).strip() return { "content_mode": "service_case_study", @@ -64,8 +70,10 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: "primary_problem": primary_problem, "desired_outcome": desired_outcome, "cta_url": cta_url, + "case_brief_file": case_brief_file, "proof_points": proof_points, "content_pillars": content_pillars, + "review_notes": review_notes, } From da1abda53d42cb93f0eb18b70aa5b27ee0c29a21 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:06:48 +0800 Subject: [PATCH 03/27] Add upstream sync helper for fork workflow --- docs/Roadmap.md | 3 +- scripts/sync_upstream.sh | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 scripts/sync_upstream.sh diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 6a5a6ac3d..ed088a9ad 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -97,4 +97,5 @@ Before adding any new feature, ask: - [ ] Define a single target customer and one offer name - [ ] Create 3 content angles from real delivery experience - [ ] Publish one short, one X post, and one site article from the same proof asset -- [ ] Update `origin` / `upstream` remotes so this fork can be pushed cleanly +- [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly +- [x] Add a dedicated upstream sync script for the fork workflow diff --git a/scripts/sync_upstream.sh b/scripts/sync_upstream.sh new file mode 100644 index 000000000..e519737a9 --- /dev/null +++ b/scripts/sync_upstream.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +set -euo pipefail + +TARGET_BRANCH="main" +AUTO_PUSH=0 + +while [ $# -gt 0 ]; do + case "$1" in + --push) + AUTO_PUSH=1 + ;; + --branch) + shift + TARGET_BRANCH="${1:-main}" + ;; + -h|--help) + cat <<'EOF' +用法: + bash scripts/sync_upstream.sh + bash scripts/sync_upstream.sh --push + bash scripts/sync_upstream.sh --branch main --push + +作用: + 1. 拉取 upstream 最新代码 + 2. 将 upstream/ 快进合并到本地 + 3. 可选推送到 origin/ + +前提: + - 当前仓库已配置 upstream 指向源仓库 + - 工作区干净 +EOF + exit 0 + ;; + *) + echo "未知参数:$1" >&2 + exit 1 + ;; + esac + shift +done + +if [ -n "$(git status --porcelain)" ]; then + echo "工作区有未提交改动,请先提交或暂存。" >&2 + exit 1 +fi + +if ! git remote get-url upstream >/dev/null 2>&1; then + echo "未配置 upstream 远程。" >&2 + exit 1 +fi + +if ! git remote get-url origin >/dev/null 2>&1; then + echo "未配置 origin 远程。" >&2 + exit 1 +fi + +current_branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null || echo "DETACHED") +if [ "$current_branch" = "DETACHED" ]; then + echo "当前处于 detached HEAD,无法自动同步。" >&2 + exit 1 +fi + +if [ "$current_branch" != "$TARGET_BRANCH" ]; then + echo "当前分支是 $current_branch,正在切换到 $TARGET_BRANCH" + git checkout "$TARGET_BRANCH" +fi + +echo "拉取 upstream/$TARGET_BRANCH ..." +git fetch upstream --prune + +echo "尝试快进合并 upstream/$TARGET_BRANCH -> $TARGET_BRANCH ..." +git merge --ff-only "upstream/$TARGET_BRANCH" + +echo "本地 $TARGET_BRANCH 已与 upstream/$TARGET_BRANCH 同步。" + +if [ "$AUTO_PUSH" -eq 1 ]; then + echo "推送到 origin/$TARGET_BRANCH ..." + git push origin "$TARGET_BRANCH" + echo "已推送到 origin/$TARGET_BRANCH。" +fi From b942ecf6472914ba6236d9dd9730edef3db60571 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:21:01 +0800 Subject: [PATCH 04/27] Refine content variants and shared sync flow --- docs/FrankMoneyPrinter.md | 13 +++++++ docs/Roadmap.md | 11 +++++- scripts/sync_upstream.sh | 80 ++++----------------------------------- src/classes/Twitter.py | 31 +++++++++++++++ src/classes/YouTube.py | 40 ++++++++++++++++++++ src/content_profile.py | 6 +++ src/main.py | 4 ++ 7 files changed, 111 insertions(+), 74 deletions(-) diff --git a/docs/FrankMoneyPrinter.md b/docs/FrankMoneyPrinter.md index 0cf68cbd5..7089a66e1 100644 --- a/docs/FrankMoneyPrinter.md +++ b/docs/FrankMoneyPrinter.md @@ -185,3 +185,16 @@ Before building anything new in this repo, ask: 3. Does it reduce delivery time on repeated service work? If not, it is probably distraction, not leverage. + +## Operating Notes + +When using this fork as a service-led lead engine, keep these constraints in mind: + +- Do not promise greenfield custom software if the real offer is deployment, hardening, or adaptation on top of existing projects. +- Do not publish sensitive client details. Use sanitized case briefs and remove secrets, domains, credentials, and private architecture specifics. +- Do not let content drift into generic AI commentary. Every post should point back to a real technical problem and a service-relevant outcome. +- Do not optimize for vanity metrics first. A post with 300 qualified impressions is better than 30,000 irrelevant views. +- Do not underprice by default. Low pricing can help cold start, but the long-term positioning depends on clarity, trust, and operational competence. +- Do not skip review. Generated content should be checked for hype, hallucinated certainty, and misalignment with the actual offer. +- Do not let outreach overrun delivery. The system only works if public proof comes from real work, not from fabricated expertise. +- Do not treat every upstream feature as useful. If it does not improve client acquisition, proof generation, or delivery reuse, it is probably out of scope for this fork. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index ed088a9ad..c39057936 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -46,7 +46,7 @@ Primary monetization order: - [x] Make X posts calm, practical, and problem-solution driven - [x] Add support for loading reusable case briefs from files - [x] Add a review step before publishing generated content -- [ ] Add content variants for `deployment`, `hardening`, and `customization` +- [x] Add content variants for `deployment`, `hardening`, and `customization` ## Phase 3: Offer Packaging @@ -91,6 +91,15 @@ Before adding any new feature, ask: 3. Does this reduce delivery friction or improve reuse? 4. If the answer is "no", it is probably off-strategy for this fork. +## Execution Guardrails + +- Keep one primary offer active at a time. Do not let the repo generate content for multiple unrelated services in parallel. +- Keep content tied to real delivery evidence. Do not manufacture authority with generic AI opinions. +- Treat security claims conservatively. "Basic hardening" is easier to defend than broad "security expert" positioning. +- Prefer sanitized case studies over abstract promises. +- Review generated assets before publishing, especially CTAs, technical claims, and screenshots. +- Protect working capital: prefer activities that shorten the path to the next paid conversation. + ## Immediate Next Tasks - [ ] Create one YouTube account and one X account using the new service-led profile fields diff --git a/scripts/sync_upstream.sh b/scripts/sync_upstream.sh index e519737a9..61cc652c9 100644 --- a/scripts/sync_upstream.sh +++ b/scripts/sync_upstream.sh @@ -2,80 +2,14 @@ set -euo pipefail -TARGET_BRANCH="main" -AUTO_PUSH=0 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +PARENT_SCRIPT="$PROJECT_ROOT/../sync_upstream_repos.sh" -while [ $# -gt 0 ]; do - case "$1" in - --push) - AUTO_PUSH=1 - ;; - --branch) - shift - TARGET_BRANCH="${1:-main}" - ;; - -h|--help) - cat <<'EOF' -用法: - bash scripts/sync_upstream.sh - bash scripts/sync_upstream.sh --push - bash scripts/sync_upstream.sh --branch main --push - -作用: - 1. 拉取 upstream 最新代码 - 2. 将 upstream/ 快进合并到本地 - 3. 可选推送到 origin/ - -前提: - - 当前仓库已配置 upstream 指向源仓库 - - 工作区干净 -EOF - exit 0 - ;; - *) - echo "未知参数:$1" >&2 - exit 1 - ;; - esac - shift -done - -if [ -n "$(git status --porcelain)" ]; then - echo "工作区有未提交改动,请先提交或暂存。" >&2 - exit 1 -fi - -if ! git remote get-url upstream >/dev/null 2>&1; then - echo "未配置 upstream 远程。" >&2 - exit 1 -fi - -if ! git remote get-url origin >/dev/null 2>&1; then - echo "未配置 origin 远程。" >&2 +if [ ! -f "$PARENT_SCRIPT" ]; then + echo "未找到上级目录脚本:$PARENT_SCRIPT" >&2 + echo "请从上级目录统一维护 sync_upstream_repos.sh。" >&2 exit 1 fi -current_branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null || echo "DETACHED") -if [ "$current_branch" = "DETACHED" ]; then - echo "当前处于 detached HEAD,无法自动同步。" >&2 - exit 1 -fi - -if [ "$current_branch" != "$TARGET_BRANCH" ]; then - echo "当前分支是 $current_branch,正在切换到 $TARGET_BRANCH" - git checkout "$TARGET_BRANCH" -fi - -echo "拉取 upstream/$TARGET_BRANCH ..." -git fetch upstream --prune - -echo "尝试快进合并 upstream/$TARGET_BRANCH -> $TARGET_BRANCH ..." -git merge --ff-only "upstream/$TARGET_BRANCH" - -echo "本地 $TARGET_BRANCH 已与 upstream/$TARGET_BRANCH 同步。" - -if [ "$AUTO_PUSH" -eq 1 ]; then - echo "推送到 origin/$TARGET_BRANCH ..." - git push origin "$TARGET_BRANCH" - echo "已推送到 origin/$TARGET_BRANCH。" -fi +exec bash "$PARENT_SCRIPT" "$PROJECT_ROOT" "$@" diff --git a/src/classes/Twitter.py b/src/classes/Twitter.py index a249ebf5a..362578c95 100644 --- a/src/classes/Twitter.py +++ b/src/classes/Twitter.py @@ -32,6 +32,33 @@ class Twitter: Class for the Bot, that grows a Twitter account. """ + def _variant_instruction(self) -> str: + """ + Returns a specialized instruction block for the selected service variant. + + Returns: + instruction (str): Variant-specific prompt guidance + """ + variant = self.content_profile.get("content_variant", "general") + + if variant == "deployment": + return ( + "Focus on shipping a real project from repo to running environment. " + "Prefer setup pitfalls, environment mismatches, hosting choices, or launch blockers." + ) + if variant == "hardening": + return ( + "Focus on security, auth, exposure, secret handling, backup gaps, or operational risk reduction." + ) + if variant == "customization": + return ( + "Focus on adapting an existing project to a workflow, client need, UI change, or integration requirement." + ) + + return ( + "Focus on practical implementation lessons that can lead into deployment, hardening, or customization work." + ) + def __init__( self, account_uuid: str, @@ -224,6 +251,8 @@ def generate_post(self) -> str: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Requirements: - Maximum 240 characters @@ -282,6 +311,8 @@ def review_post(self, draft: str) -> str: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Requirements: - Keep the core meaning diff --git a/src/classes/YouTube.py b/src/classes/YouTube.py index 8ea567c2c..e0b20efde 100644 --- a/src/classes/YouTube.py +++ b/src/classes/YouTube.py @@ -53,6 +53,32 @@ class YouTube: 7. Combine Concatenated Images with the Text-to-Speech [DONE] """ + def _variant_instruction(self) -> str: + """ + Returns specialized guidance for the selected service-led content variant. + + Returns: + instruction (str): Variant-specific prompt guidance + """ + variant = self.content_profile.get("content_variant", "general") + + if variant == "deployment": + return ( + "Emphasize repo-to-production setup, environment mismatches, hosting trade-offs, and why local success often fails after deployment." + ) + if variant == "hardening": + return ( + "Emphasize auth, exposed surfaces, secret handling, backup gaps, abuse prevention, and practical risk reduction." + ) + if variant == "customization": + return ( + "Emphasize adapting an existing project to a workflow, buyer requirement, UI change, or integration path." + ) + + return ( + "Emphasize concrete implementation lessons that can naturally lead into deployment, hardening, or customization work." + ) + def __init__( self, account_uuid: str, @@ -157,6 +183,8 @@ def generate_topic(self) -> str: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Generate one concrete short-video angle in exactly one sentence. @@ -198,6 +226,8 @@ def generate_script(self) -> str: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Script goals: - Attract the right prospect, not broad entertainment traffic. @@ -277,6 +307,8 @@ def generate_metadata(self) -> dict: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Requirements: - Under 90 characters @@ -307,6 +339,8 @@ def generate_metadata(self) -> dict: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Requirements: - Summarize the lesson in 2-4 short lines @@ -348,6 +382,8 @@ def generate_prompts(self) -> List[str]: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Visual direction: - product UI mockups @@ -452,6 +488,8 @@ def review_script(self, draft: str) -> str: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Requirements: - Keep it concise and practical @@ -488,6 +526,8 @@ def review_metadata(self, draft_metadata: dict) -> dict: {build_profile_context(self.content_profile)} Reusable case brief: {self.case_brief or "None"} + Variant guidance: + {self._variant_instruction()} Return valid JSON only with this schema: {{ diff --git a/src/content_profile.py b/src/content_profile.py index 901986424..55e0bf154 100644 --- a/src/content_profile.py +++ b/src/content_profile.py @@ -44,6 +44,7 @@ def normalize_content_profile(content_profile: dict | None) -> dict: profile = { "content_mode": str(raw.get("content_mode", "") or "").strip().lower(), + "content_variant": str(raw.get("content_variant", "") or "").strip().lower(), "target_customer": str(raw.get("target_customer", "") or "").strip(), "offer_name": str(raw.get("offer_name", "") or "").strip(), "primary_problem": str(raw.get("primary_problem", "") or "").strip(), @@ -71,6 +72,9 @@ def normalize_content_profile(content_profile: dict | None) -> dict: ) profile["content_mode"] = "service_case_study" if has_strategy_data else "legacy" + if not profile["content_variant"]: + profile["content_variant"] = "general" + return profile @@ -103,6 +107,8 @@ def build_profile_context(content_profile: dict | None) -> str: lines = [] if profile["target_customer"]: lines.append(f"Target customer: {profile['target_customer']}") + if profile["content_variant"]: + lines.append(f"Content variant: {profile['content_variant']}") if profile["offer_name"]: lines.append(f"Offer: {profile['offer_name']}") if profile["primary_problem"]: diff --git a/src/main.py b/src/main.py index f8ec07616..1edf5acc2 100644 --- a/src/main.py +++ b/src/main.py @@ -44,6 +44,9 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: target_customer = question( " => Target customer (e.g. indie hackers, founders, small teams): " ).strip() + content_variant = question( + " => Content variant (deployment/hardening/customization/general): " + ).strip().lower() offer_name = question( f" => Main offer promoted by this {account_type} account: " ).strip() @@ -65,6 +68,7 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: return { "content_mode": "service_case_study", + "content_variant": content_variant or "general", "target_customer": target_customer, "offer_name": offer_name, "primary_problem": primary_problem, From 76900c7882dfa320788d8cd7302a7bc390eff3dc Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:29:14 +0800 Subject: [PATCH 05/27] Add homepage copy and ignore excalidraw log --- .gitignore | 3 +- docs/FzhangHomepageCopy.md | 343 +++++++++++++++++++++++++++++++++++++ 2 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 docs/FzhangHomepageCopy.md diff --git a/.gitignore b/.gitignore index 423652649..72a0a91df 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ google-maps-scraper-0.9.7/ niche.txt *.exe auto.sh -.DS_Store \ No newline at end of file +.DS_Store +excalidraw.log diff --git a/docs/FzhangHomepageCopy.md b/docs/FzhangHomepageCopy.md new file mode 100644 index 000000000..fcc3f2d8d --- /dev/null +++ b/docs/FzhangHomepageCopy.md @@ -0,0 +1,343 @@ +# fzhang.dev Homepage Copy + +This draft assumes the homepage has one primary goal: + +> Turn founders and small teams with tooling or deployment friction into booked conversations. + +Primary CTA: + +- `预约一次项目诊断` + +Secondary CTA: + +- `查看案例与文章` + +## Positioning + +### Headline Options + +Option A: + +- `把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本` + +Option B: + +- `从 GitHub 项目到可交付系统` + +Option C: + +- `帮你部署、加固并改造开源 AI / Web 项目` + +### Recommended Headline + +`把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本` + +### Subheadline Options + +Option A: + +- `我帮助个人创业者、小团队和产品负责人,把开源项目从“本地能跑”推进到“线上可用、风险可控、贴合业务流程”。` + +Option B: + +- `如果你已经选好了一个 GitHub 项目,但部署卡住、配置混乱、存在安全隐患,或者还需要按你的业务流程做定制化改造,我可以帮你把第一版落到可用。` + +### Recommended Subheadline + +`如果你已经选好了一个 GitHub 项目,但部署卡住、配置混乱、存在安全隐患,或者还需要按你的业务流程做定制化改造,我可以帮你把第一版落到可用。` + +### Hero CTA + +- Primary: `预约一次项目诊断` +- Secondary: `查看最近案例` + +## Hero Proof Strip + +Use a short proof strip directly under the fold: + +- `适合:独立开发者、AI 创业者、小团队` +- `服务方向:部署 / 基础加固 / 二次改造` +- `工作方式:先诊断,再交付,再沉淀为可复用文档` + +## Problem Section + +### Section Title + +`大多数项目不是死在“不会写”,而是死在“跑不起来”` + +### Body Copy + +- `很多人已经找到了合适的开源项目,也知道自己想做什么,但真正卡住他们的往往不是创意,而是部署、配置、权限、反代、环境变量、数据库连接、第三方接入,以及改到一半之后发现整个流程根本不贴合实际业务。` +- `你不一定需要从零开发一个全新系统。很多时候,你需要的是一个人,把现成项目梳理清楚,跑起来,补上明显风险点,再按你的实际工作流改成能交付的版本。` + +## What I Do Section + +### Section Title + +`我主要做三件事` + +### Card 1 + +Title: + +- `开源项目部署` + +Copy: + +- `把你选中的 GitHub 项目部署到本地或服务器,处理环境配置、域名、HTTPS、基础运行问题,让它先真正跑起来。` + +### Card 2 + +Title: + +- `基础加固` + +Copy: + +- `针对暴露面、鉴权、密钥、备份、配置混乱等明显风险点做一轮基础整理和加固,让项目不只是能跑,而且更稳。` + +### Card 3 + +Title: + +- `二次改造` + +Copy: + +- `在已有项目上做功能微调、流程适配、UI 调整或集成改造,让它更贴近你的业务而不是停留在 demo 阶段。` + +## Who It’s For Section + +### Section Title + +`这类服务最适合这些人` + +### Copy + +- `已经有明确方向,但不想从零开发的独立开发者` +- `希望把开源 AI 工具落地成可用工作流的小团队` +- `已经试过自己部署,但卡在配置、上线或稳定性问题上的创业者` +- `知道自己想要什么结果,但不想把时间继续浪费在环境问题和重复试错上的产品负责人` + +## Why Me Section + +### Section Title + +`你不需要一个只会说“可以试试”的人` + +### Body Copy + +- `我更擅长的不是空谈方案,而是从杂乱需求里提炼出真实问题,借助 AI 和现有工具,把项目推进到能运行、能交付、能继续维护的状态。` +- `相比泛化的“什么都能做”,我更关注三件事:需求能不能讲清、项目能不能落地、风险有没有提前处理。` +- `如果一个项目不该做、暂时不值得做,或者现在的做法成本太高,我也会直接说。` + +## Process Section + +### Section Title + +`合作流程` + +### Steps + +1. `先诊断` + `你把目标、现状、代码仓库或部署环境发给我,我先判断问题在哪里,值不值得做。` + +2. `再定范围` + `只定义当前阶段真正需要的交付,不把项目做成无限扩张的需求黑洞。` + +3. `然后交付` + `我完成部署、基础加固或改造,并留下必要说明,方便你后续继续使用和维护。` + +4. `最后决定是否继续` + `如果第一阶段有效,再进入下一轮迭代,而不是一开始就把所有预算和时间压上去。` + +## Pricing Section + +### Section Title + +`服务与报价` + +### Intro Copy + +- `以下是当前阶段的标准化起步方案。具体价格会根据项目复杂度、现有代码质量、第三方依赖、交付时限和是否需要持续支持而调整。` + +### Package 1 + +Name: + +- `项目诊断` + +Price: + +- `¥199 - ¥499` + +Best for: + +- `还不确定问题在哪里,想先判断项目值不值得继续做的人` + +Includes: + +- `30-45 分钟沟通` +- `现状梳理` +- `主要问题点与下一步建议` +- `适合的话给出后续交付方向` + +CTA: + +- `先做一次诊断` + +### Package 2 + +Name: + +- `Deployment Sprint` + +Price: + +- `¥999 起` + +Best for: + +- `已经选好项目,但部署、配置、上线卡住的人` + +Includes: + +- `部署到本地或服务器` +- `基础环境配置` +- `域名 / HTTPS / 启动说明` +- `一轮基础问题排查` + +CTA: + +- `咨询部署 Sprint` + +### Package 3 + +Name: + +- `Hardening Pass` + +Price: + +- `¥1499 起` + +Best for: + +- `项目已经能跑,但暴露面、配置、风险点比较混乱的人` + +Includes: + +- `基础安全与稳定性检查` +- `鉴权 / 密钥 / 反代 / 备份建议` +- `高风险项说明` +- `一轮基础整理与修正` + +CTA: + +- `咨询加固服务` + +### Package 4 + +Name: + +- `Customization Sprint` + +Price: + +- `¥2999 起` + +Best for: + +- `不想从零开发,只想把现有项目改成更贴合业务版本的人` + +Includes: + +- `需求澄清` +- `已有项目上的功能或流程改造` +- `必要的 UI / 集成适配` +- `阶段性交付说明` + +CTA: + +- `咨询改造 Sprint` + +### Custom Tier + +Name: + +- `长期支持 / 组合交付` + +Price: + +- `按范围报价` + +Copy: + +- `如果你需要持续迭代、分阶段推进,或者部署、加固、改造需要组合进行,可以按实际范围单独报价。` + +## FAQ Section + +### FAQ 1 + +Q: + +- `你是从零开发,还是更偏向在现有项目上做交付?` + +A: + +- `现阶段我更推荐在现有开源项目或已有代码基础上推进。这样成本更可控,交付速度更快,也更适合当前大多数创业团队的真实需求。` + +### FAQ 2 + +Q: + +- `如果我还不确定该选哪个 GitHub 项目怎么办?` + +A: + +- `可以先从项目诊断开始。我会先根据你的目标、预算、时间和维护能力,帮你判断现成项目是否适合,或者现在是否应该继续推进。` + +### FAQ 3 + +Q: + +- `你会承诺“绝对安全”或者“完全无 bug”吗?` + +A: + +- `不会。我更倾向于给出保守、真实、可验证的交付承诺。现阶段可以做的是基础加固、明显风险排查和实用性的稳定性改进,而不是夸大承诺。` + +### FAQ 4 + +Q: + +- `我应该先做部署、加固还是改造?` + +A: + +- `多数情况下应该先把项目跑起来,再判断哪些风险必须先处理,最后再做更贴近业务的改造。也正因为如此,先做诊断通常更省钱。` + +## Final CTA Section + +### Title + +`先把第一版跑起来,再决定值不值得继续加码` + +### Copy + +- `如果你手上已经有一个想落地的开源 AI / Web 项目,但现在卡在部署、配置、风险点或改造方向上,先做一次诊断。` +- `比起继续在环境问题上反复试错,更有效的做法,是先把问题讲清楚,再决定下一步怎么做。` + +### CTA + +- `预约一次项目诊断` + +## Short Meta Draft + +### Title Tag + +- `开源 AI / Web 项目部署、加固与改造 | fzhang.dev` + +### Meta Description + +- `帮助创业者和小团队把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本。提供部署、基础加固、二次改造与项目诊断服务。` From d91ddc8f3393868a2fac6757251bc9dd5d6a104d Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:10:07 +0800 Subject: [PATCH 06/27] Reframe fork around asset compounding --- README.md | 14 +- docs/FrankMoneyPrinter.md | 307 ++++++++++++++++++------------- docs/FzhangHomepageCopy.md | 368 ++++++++++--------------------------- docs/Roadmap.md | 193 +++++++++++-------- 4 files changed, 399 insertions(+), 483 deletions(-) diff --git a/README.md b/README.md index 629e834d2..35ad02198 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MoneyPrinter V2 -Frank's fork turns MPV2 from a generic faceless-content tool into a client-acquisition engine for service-led AI work: case-study Shorts, cross-platform distribution, and targeted outreach for open-source AI / web deployment, hardening, and customization work. +Frank's fork is being repurposed from a generic faceless-content tool into a long-term income asset printer: long-tail content generation, cross-platform distribution, owned-audience capture, and monetization experiments around AI / developer workflows. Sponsored by Post Bridge @@ -18,7 +18,7 @@ Sponsored by Post Bridge [![Discord](https://img.shields.io/discord/1134848537704804432?style=for-the-badge)](https://dsc.gg/fuji-community) An application that automates repetitive parts of online monetization. -MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of the MoneyPrinter project. This fork keeps the modular core, but specializes it around proof-driven marketing for technical services instead of generic traffic farming. +MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of the MoneyPrinter project. This fork keeps the modular core, but is being redirected toward owned content assets, conversion paths, and low-touch revenue experiments instead of pure service lead generation. > **Note:** MPV2 needs Python 3.12 to function effectively. > Watch the YouTube video [here](https://youtu.be/wAZ_ZSuIqfk) @@ -34,12 +34,12 @@ MPV2 (MoneyPrinter Version 2) is, as the name suggests, the second version of th ## This Fork's Goal -This fork is optimized for a narrower business model: +This fork is being re-optimized around long-term monetizable assets: -- attract founders, indie hackers, and small teams -- publish technical case-study content instead of generic faceless clips -- turn real delivery work into proof assets -- use outreach to find buyers for deployment, hardening, and customization services +- publish reusable content with long-tail utility +- turn distribution into owned audience instead of one-off impressions +- direct attention toward assets such as newsletters, resource packs, templates, and selective affiliate offers +- treat service revenue as optional bootstrap fuel, not the end state See [docs/FrankMoneyPrinter.md](docs/FrankMoneyPrinter.md) for the specialization strategy and [docs/Roadmap.md](docs/Roadmap.md) for the implementation phases. diff --git a/docs/FrankMoneyPrinter.md b/docs/FrankMoneyPrinter.md index 7089a66e1..7c85000d7 100644 --- a/docs/FrankMoneyPrinter.md +++ b/docs/FrankMoneyPrinter.md @@ -1,200 +1,249 @@ # Frank's MoneyPrinter -## What This Fork Is +## Reset -This is not a generic "AI makes money online" machine. +This fork should not stop at becoming "one more client acquisition helper". -For Frank, this fork is a: +If it only helps win more custom work, it is useful, but it is not really a `MoneyPrinter`. -- proof engine -- content engine -- outreach engine +For Frank, the more accurate target is: -It exists to support one concrete service business: +> A system that continuously creates, distributes, and compounds monetizable content and audience assets. -> Help founders and small teams deploy, harden, and adapt open-source AI / web projects so they become usable in the real world. +That means the fork should move away from "more ways to sell hours" and closer to: -## What This Fork Is Not +- more reusable content +- more owned attention +- more conversion paths into assets +- more low-touch or no-touch monetization -This fork is not optimized for: +## The Three Printers -- faceless entertainment channels -- broad affiliate spam -- generic motivational AI content -- waiting for platform ad revenue as the first monetization layer +To avoid future confusion, separate the business layers clearly: -Those paths are slower, noisier, and less aligned with Frank's actual strengths. +### 1. Cash Printer -## Core Strengths This Fork Must Amplify +Prints: -Based on the discovery work, the fork should amplify: +- active revenue +- delivery revenue +- consulting / implementation income -- extracting precise requirements from messy input -- solving technical problems with AI as a force multiplier -- explaining complex topics clearly -- documenting work so it becomes reusable -- operating with a security-aware mindset +Use case: -## Business Thesis +- useful for survival +- useful for early proof +- not the final destination -Frank is currently strongest as: +### 2. Lead Printer -> An AI-assisted delivery-focused problem solver. +Prints: -Near-term positioning: +- inbound attention +- qualified subscribers +- repeated visibility +- search and social entry points -> Open-source AI / web project deployment, hardening, and customization. +Use case: -This is stronger than vague labels like "website developer" or "consultant" because it: +- makes future sales cheaper +- feeds both service and product revenue -- maps to real evidence -- is easier to explain -- is easier to price -- creates better case-study content +### 3. Asset Printer -## Offer Ladder +Prints: -### 1. Deployment Sprint +- reusable content assets +- affiliate pages +- comparison pages +- email lists +- resource packs +- templates +- digital products -Best for: +Use case: -- customers who picked a GitHub project but cannot get it running +- closest to the real meaning of "printer" +- scales better than direct service work +- becomes more durable over time -Output: +## Which Printer This Fork Should Optimize For -- local or server deployment -- environment setup -- domain / HTTPS / basic launch notes +Primary target: -### 2. Hardening Pass +- Asset Printer -Best for: +Secondary target: -- projects that run but are fragile, overexposed, or badly configured +- Lead Printer -Output: +Tertiary / bootstrap only: -- basic hardening review -- auth / env / proxy / backup suggestions -- concrete risk notes +- Cash Printer -### 3. Customization Sprint +This order matters. -Best for: +Service revenue can still exist, but it should support asset building rather than replace it. -- buyers who do not want a greenfield build -- buyers who want an existing project adapted to their real workflow +## What This Fork Should Produce -Output: +This fork should gradually become a pipeline that turns one idea or one proof point into multiple reusable assets: -- scoped changes on top of an existing codebase -- UI / workflow / integration adjustments +1. a short-form video +2. a thread / short post +3. a longer article or note +4. an owned capture point +5. a monetization path -## Content Strategy +That monetization path may be: -Content is not the business model. +- newsletter signup +- downloadable checklist +- template pack +- paid SOP +- affiliate recommendation +- low-touch productized service -Content is evidence that Frank can: +The fork should not assume every content unit ends in "book a call". -- make complex systems work -- avoid naive mistakes -- turn vague requirements into practical outcomes +## Strategic Principle -### Content Pillars +Do not ask: -- deployment lessons -- hardening and risk reduction -- open-source project teardowns -- workflow adaptation and customization -- calm technical judgment for non-expert buyers +> How can this repo help me get one more client? -### Short-Form Content Pattern +Ask: -Every short should follow one of these angles: +> How can this repo help me create one more durable income asset? -- what usually breaks -- what most people miss -- how to deploy this properly -- how to reduce one expensive risk -- how to adapt an existing project to a real use case +## Suitable Monetization Types -### Tone +### Strong fit -- calm -- specific -- operator-like -- no fake hustle energy -- no empty AI hot takes +- long-tail technical content +- search-friendly tutorials +- tool comparison content +- deployment / risk / cost guides +- curated resource packs +- paid checklists and SOPs +- affiliate recommendations for tools you actually use +- email capture tied to technical utility -## Outreach Strategy +### Medium fit -Outreach should target: +- low-touch standardized audits +- productized deployment bundles +- starter kits -- indie hackers -- small SaaS teams -- operators with visible tooling pain -- buyers already trying to use open-source tools +### Weak fit -Outreach should not say: +- broad freelance bidding +- generic "AI agency" marketing +- pure personality-driven content +- entertainment-first faceless content -- "I can do anything" -- "I am an AI expert" -- "I offer consulting" +## What Existing Strengths Still Matter -Outreach should say: +The discovery work still stands, but it should be pointed at assets: -- I can help you get this running -- I can harden this setup -- I can adapt this project to your workflow +- extracting precise needs from messy input +- using AI to turn ideas into concrete outputs quickly +- documenting work in reusable form +- staying relatively calm and explicit +- recognizing security and operational risk -## Product Direction +These strengths are still valuable, but instead of only producing custom delivery, they should also produce: -This fork should move through these layers in order: +- reusable pages +- reusable checklists +- reusable scripts +- reusable conversion funnels -1. paid delivery -2. public proof -3. repeatable templates -4. productized services -5. selective digital products / affiliate later +## New Content Strategy -If a future idea skips layer 1 and layer 2, it is probably premature for this fork. +Content should be chosen by monetizable intent, not by broad self-expression. -## Public Fork Lessons +### Better content types -Publicly visible evolution around MoneyPrinter-like tools points in a few directions: +- "how to deploy X without breaking Y" +- "what usually goes wrong when teams self-host X" +- "X vs Y for this exact workflow" +- "what is worth paying for vs what to self-host" +- "how to reduce one expensive deployment / security mistake" +- "what I would use if I had to start from zero" -- stronger localization -- web UI and easier setup -- better TTS / subtitles / media quality -- multi-platform distribution -- more robust automation surfaces +### Weaker content types -Frank's fork intentionally takes a different angle: +- generic AI commentary +- broad hot takes +- vague productivity advice +- inspirational tech writing without monetizable intent -- less generic media volume -- more business relevance -- more proof from real delivery work -- better alignment with service revenue +## Audience Logic -## Operational Rules +Not every visitor needs to become a service lead. -Before building anything new in this repo, ask: +The audience can split into: -1. Does it help attract or convert the right client? -2. Does it help turn real work into reusable proof? -3. Does it reduce delivery time on repeated service work? +- readers who subscribe +- readers who download +- readers who click affiliate links +- readers who buy a small digital product +- readers who later become service buyers -If not, it is probably distraction, not leverage. +This is healthier than forcing all traffic into direct selling. -## Operating Notes +## Website Logic -When using this fork as a service-led lead engine, keep these constraints in mind: +`fzhang.dev` should remain primarily a content site, not a hard sales page. -- Do not promise greenfield custom software if the real offer is deployment, hardening, or adaptation on top of existing projects. -- Do not publish sensitive client details. Use sanitized case briefs and remove secrets, domains, credentials, and private architecture specifics. -- Do not let content drift into generic AI commentary. Every post should point back to a real technical problem and a service-relevant outcome. -- Do not optimize for vanity metrics first. A post with 300 qualified impressions is better than 30,000 irrelevant views. -- Do not underprice by default. Low pricing can help cold start, but the long-term positioning depends on clarity, trust, and operational competence. -- Do not skip review. Generated content should be checked for hype, hallucinated certainty, and misalignment with the actual offer. -- Do not let outreach overrun delivery. The system only works if public proof comes from real work, not from fabricated expertise. -- Do not treat every upstream feature as useful. If it does not improve client acquisition, proof generation, or delivery reuse, it is probably out of scope for this fork. +Recommended role split: + +- homepage = trust + navigation + selected conversion paths +- articles = long-tail traffic and credibility +- dedicated pages = resource capture, product pages, affiliate pages, selective service pages + +Do not overcorrect the site into a generic agency homepage. + +## Transition Rule + +The current codebase already contains some service-led logic. + +That is acceptable as a transitional layer, but future changes should bias toward: + +- asset generation +- asset reuse +- audience capture +- monetization experiments + +and away from: + +- purely one-off service CTAs +- generic cold outreach logic +- content that only makes sense as custom work proof + +## Operating Rules + +Before building anything new, ask: + +1. Does this help create a reusable asset? +2. Does this help build owned audience instead of rented reach? +3. Does this make future monetization more automatic or lower-touch? +4. If it only helps sell more hours, is it still worth the complexity? + +If the answer to 1-3 is "no", be skeptical. + +## Practical Guardrails + +- Do not turn every content unit into a direct sales pitch. +- Do not optimize for vanity metrics at the expense of monetizable intent. +- Do not assume affiliate links alone are enough; pair them with owned capture and utility. +- Do not create assets that require constant manual babysitting. +- Do not let the repo become a second freelance platform profile manager. +- Do not confuse short-term cash optimization with long-term printer design. + +## Current Best Interpretation + +For Frank, `MoneyPrinterV2` should become: + +> A content-asset production and distribution system that compounds into owned audience, monetizable pages, and low-touch revenue streams. diff --git a/docs/FzhangHomepageCopy.md b/docs/FzhangHomepageCopy.md index fcc3f2d8d..c7acd46ea 100644 --- a/docs/FzhangHomepageCopy.md +++ b/docs/FzhangHomepageCopy.md @@ -1,343 +1,165 @@ -# fzhang.dev Homepage Copy +# fzhang.dev Homepage Direction -This draft assumes the homepage has one primary goal: +This document replaces the previous service-heavy homepage draft. -> Turn founders and small teams with tooling or deployment friction into booked conversations. +After re-evaluating the strategy, the homepage should **not** become a generic service landing page. -Primary CTA: +`fzhang.dev` works better as: -- `预约一次项目诊断` +- a trust-building content site +- a long-tail traffic surface +- an owned-audience capture surface -Secondary CTA: +The homepage should therefore: -- `查看案例与文章` +1. keep the blog / thinking-site identity +2. make one owned-asset CTA visible +3. optionally leave a light path to service, without letting service dominate -## Positioning +## Homepage Job -### Headline Options +Primary job: -Option A: +- help the right readers understand what the site is about +- guide them toward a repeatable relationship -- `把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本` +Recommended primary action: -Option B: +- `订阅更新` +- or `领取一份免费资源` -- `从 GitHub 项目到可交付系统` +Recommended secondary action: -Option C: +- `查看文章归档` -- `帮你部署、加固并改造开源 AI / Web 项目` +Optional tertiary action: -### Recommended Headline +- `了解我还能提供什么` -`把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本` +Do not make "book a call" the main homepage CTA unless the whole site is deliberately being repositioned away from content. -### Subheadline Options +## Recommended Homepage Adjustment -Option A: +Keep the existing hero structure, but add a more strategic sentence. -- `我帮助个人创业者、小团队和产品负责人,把开源项目从“本地能跑”推进到“线上可用、风险可控、贴合业务流程”。` +### Current direction -Option B: +The current site already communicates: -- `如果你已经选好了一个 GitHub 项目,但部署卡住、配置混乱、存在安全隐患,或者还需要按你的业务流程做定制化改造,我可以帮你把第一版落到可用。` +- technical writing +- practical reflection +- searchable knowledge -### Recommended Subheadline +That is good and should remain. -`如果你已经选好了一个 GitHub 项目,但部署卡住、配置混乱、存在安全隐患,或者还需要按你的业务流程做定制化改造,我可以帮你把第一版落到可用。` +### Recommended hero subtitle revision -### Hero CTA +Current site language is close to: -- Primary: `预约一次项目诊断` -- Secondary: `查看最近案例` +- `写 macOS、Vim、AI 与学习方法的实践与思考` -## Hero Proof Strip +Suggested stronger version: -Use a short proof strip directly under the fold: +- `写 macOS、Vim、AI 与学习方法,也持续整理那些值得长期保存、复用和变现的技术经验。` -- `适合:独立开发者、AI 创业者、小团队` -- `服务方向:部署 / 基础加固 / 二次改造` -- `工作方式:先诊断,再交付,再沉淀为可复用文档` +This keeps the blog identity while subtly moving toward asset thinking. -## Problem Section +## New Homepage Block -### Section Title +Add one lightweight block below the hero and above recent posts. -`大多数项目不是死在“不会写”,而是死在“跑不起来”` +### Section title -### Body Copy +- `如果你想看的是可长期复用的技术资产` -- `很多人已经找到了合适的开源项目,也知道自己想做什么,但真正卡住他们的往往不是创意,而是部署、配置、权限、反代、环境变量、数据库连接、第三方接入,以及改到一半之后发现整个流程根本不贴合实际业务。` -- `你不一定需要从零开发一个全新系统。很多时候,你需要的是一个人,把现成项目梳理清楚,跑起来,补上明显风险点,再按你的实际工作流改成能交付的版本。` +### Body copy -## What I Do Section +- `这里不只记录零散经验。我更关心的是:哪些排障过程、工具判断、部署教训和 AI 工作流,值得被整理成可以反复搜索、反复引用、甚至延伸成资源包、模板或长期专题的内容。` +- `如果你也更在意“长期可复用价值”而不是一时的信息刺激,可以从文章归档开始,或者直接订阅后续更新。` -### Section Title +### CTA options -`我主要做三件事` +- Primary: `订阅更新` +- Secondary: `查看文章归档` +- Optional: `领取免费清单` -### Card 1 +## Stronger Version If You Want One Resource CTA -Title: +If you are ready to test owned capture, replace the optional CTA with a real asset. -- `开源项目部署` +Examples: -Copy: +- `领取开源 AI 项目部署检查清单` +- `领取自部署项目常见风险速查表` +- `获取独立开发者 AI 工具栈清单` -- `把你选中的 GitHub 项目部署到本地或服务器,处理环境配置、域名、HTTPS、基础运行问题,让它先真正跑起来。` +The homepage should then introduce that asset briefly: -### Card 2 +### Section title -Title: +- `先拿一份免费清单` -- `基础加固` +### Body copy -Copy: +- `如果你正在自部署开源 AI / Web 项目,或者正在筛选哪些工具值得真正投入,可以先从一份免费清单开始。它比零散收藏更适合回看,也更适合后续真正动手。` -- `针对暴露面、鉴权、密钥、备份、配置混乱等明显风险点做一轮基础整理和加固,让项目不只是能跑,而且更稳。` - -### Card 3 - -Title: - -- `二次改造` - -Copy: - -- `在已有项目上做功能微调、流程适配、UI 调整或集成改造,让它更贴近你的业务而不是停留在 demo 阶段。` - -## Who It’s For Section - -### Section Title - -`这类服务最适合这些人` - -### Copy - -- `已经有明确方向,但不想从零开发的独立开发者` -- `希望把开源 AI 工具落地成可用工作流的小团队` -- `已经试过自己部署,但卡在配置、上线或稳定性问题上的创业者` -- `知道自己想要什么结果,但不想把时间继续浪费在环境问题和重复试错上的产品负责人` - -## Why Me Section - -### Section Title - -`你不需要一个只会说“可以试试”的人` - -### Body Copy - -- `我更擅长的不是空谈方案,而是从杂乱需求里提炼出真实问题,借助 AI 和现有工具,把项目推进到能运行、能交付、能继续维护的状态。` -- `相比泛化的“什么都能做”,我更关注三件事:需求能不能讲清、项目能不能落地、风险有没有提前处理。` -- `如果一个项目不该做、暂时不值得做,或者现在的做法成本太高,我也会直接说。` - -## Process Section - -### Section Title - -`合作流程` - -### Steps - -1. `先诊断` - `你把目标、现状、代码仓库或部署环境发给我,我先判断问题在哪里,值不值得做。` - -2. `再定范围` - `只定义当前阶段真正需要的交付,不把项目做成无限扩张的需求黑洞。` - -3. `然后交付` - `我完成部署、基础加固或改造,并留下必要说明,方便你后续继续使用和维护。` - -4. `最后决定是否继续` - `如果第一阶段有效,再进入下一轮迭代,而不是一开始就把所有预算和时间压上去。` - -## Pricing Section - -### Section Title - -`服务与报价` - -### Intro Copy - -- `以下是当前阶段的标准化起步方案。具体价格会根据项目复杂度、现有代码质量、第三方依赖、交付时限和是否需要持续支持而调整。` - -### Package 1 - -Name: - -- `项目诊断` - -Price: - -- `¥199 - ¥499` - -Best for: - -- `还不确定问题在哪里,想先判断项目值不值得继续做的人` - -Includes: - -- `30-45 分钟沟通` -- `现状梳理` -- `主要问题点与下一步建议` -- `适合的话给出后续交付方向` - -CTA: - -- `先做一次诊断` - -### Package 2 - -Name: - -- `Deployment Sprint` - -Price: - -- `¥999 起` - -Best for: - -- `已经选好项目,但部署、配置、上线卡住的人` - -Includes: - -- `部署到本地或服务器` -- `基础环境配置` -- `域名 / HTTPS / 启动说明` -- `一轮基础问题排查` - -CTA: - -- `咨询部署 Sprint` - -### Package 3 - -Name: - -- `Hardening Pass` - -Price: - -- `¥1499 起` - -Best for: - -- `项目已经能跑,但暴露面、配置、风险点比较混乱的人` - -Includes: - -- `基础安全与稳定性检查` -- `鉴权 / 密钥 / 反代 / 备份建议` -- `高风险项说明` -- `一轮基础整理与修正` - -CTA: - -- `咨询加固服务` - -### Package 4 - -Name: - -- `Customization Sprint` - -Price: - -- `¥2999 起` - -Best for: - -- `不想从零开发,只想把现有项目改成更贴合业务版本的人` - -Includes: - -- `需求澄清` -- `已有项目上的功能或流程改造` -- `必要的 UI / 集成适配` -- `阶段性交付说明` - -CTA: - -- `咨询改造 Sprint` - -### Custom Tier - -Name: - -- `长期支持 / 组合交付` - -Price: - -- `按范围报价` - -Copy: - -- `如果你需要持续迭代、分阶段推进,或者部署、加固、改造需要组合进行,可以按实际范围单独报价。` - -## FAQ Section - -### FAQ 1 - -Q: - -- `你是从零开发,还是更偏向在现有项目上做交付?` - -A: - -- `现阶段我更推荐在现有开源项目或已有代码基础上推进。这样成本更可控,交付速度更快,也更适合当前大多数创业团队的真实需求。` - -### FAQ 2 - -Q: - -- `如果我还不确定该选哪个 GitHub 项目怎么办?` +### CTA -A: +- `领取免费清单` -- `可以先从项目诊断开始。我会先根据你的目标、预算、时间和维护能力,帮你判断现成项目是否适合,或者现在是否应该继续推进。` +## What Not To Do -### FAQ 3 +- Do not turn the homepage into a hard service pitch. +- Do not place a large pricing table on the homepage. +- Do not let direct service CTAs overpower subscription and content navigation. +- Do not make the site feel like a generic "AI agency" page. -Q: +## About Page Direction -- `你会承诺“绝对安全”或者“完全无 bug”吗?` +The About page should carry more of the "what I do beyond writing" signal. -A: +Recommended addition: -- `不会。我更倾向于给出保守、真实、可验证的交付承诺。现阶段可以做的是基础加固、明显风险排查和实用性的稳定性改进,而不是夸大承诺。` +### Section title -### FAQ 4 +- `除了写作,我还在做什么` -Q: +### Body copy -- `我应该先做部署、加固还是改造?` +- `除了持续写作,我也在关注另一件事:如何把真实技术经验整理成可复用的内容资产,而不是只停留在项目交付和聊天记录里。` +- `这也是为什么这里的很多文章,会天然关注排障路径、工具判断、部署教训、AI 协作中的认知问题,以及哪些经验值得被整理成长期可用的资源。` -A: +This supports the new direction without turning About into a sales page. -- `多数情况下应该先把项目跑起来,再判断哪些风险必须先处理,最后再做更贴近业务的改造。也正因为如此,先做诊断通常更省钱。` +## Service Positioning On Site -## Final CTA Section +If you still want a service path, keep it light: -### Title +- homepage = light mention only +- about = one paragraph +- dedicated page = full detail -`先把第一版跑起来,再决定值不值得继续加码` +That keeps the site aligned with the new MoneyPrinter direction: -### Copy +- content first +- owned audience second +- monetization paths third -- `如果你手上已经有一个想落地的开源 AI / Web 项目,但现在卡在部署、配置、风险点或改造方向上,先做一次诊断。` -- `比起继续在环境问题上反复试错,更有效的做法,是先把问题讲清楚,再决定下一步怎么做。` +## Recommended Homepage CTA Hierarchy -### CTA +1. `订阅更新` +2. `查看文章归档` +3. `领取免费清单` or `了解更多` +4. optional service link, but not primary -- `预约一次项目诊断` +## Meta Direction -## Short Meta Draft +Homepage title tag should stay content-led, not agency-led. -### Title Tag +Suggested title: -- `开源 AI / Web 项目部署、加固与改造 | fzhang.dev` +- `Frank Zhang 的技术与思考 | macOS、Vim、AI 与长期可复用的技术经验` -### Meta Description +Suggested meta description: -- `帮助创业者和小团队把开源 AI / Web 项目真正跑起来、稳起来、改成能用的版本。提供部署、基础加固、二次改造与项目诊断服务。` +- `记录 macOS、Vim、AI 与学习方法的实践与思考,也持续整理那些值得长期保存、复用和延伸成技术资产的经验。` diff --git a/docs/Roadmap.md b/docs/Roadmap.md index c39057936..ccc265684 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -1,110 +1,155 @@ # Frank MoneyPrinter Roadmap -This roadmap keeps the fork aligned with one business objective: +This roadmap is now aligned to a different end state: -> Turn real open-source AI / web delivery work into proof-driven content, targeted outreach, and paid service revenue. +> Build a system that compounds content, audience, and monetizable assets into longer-term income channels. -The default upstream "faceless content at scale" path is not the primary strategy for this fork. +The fork is no longer primarily optimized around "more client work". -## Positioning +## North Star -Primary role: +The system should gradually make it easier to produce: -- Open-source AI / web project deployment -- Basic hardening and risk reduction -- Business-facing customization on top of existing projects +- long-tail traffic assets +- owned audience +- reusable monetization pages +- low-touch offers +- selective affiliate and digital-product revenue -Primary audience: +## Success Criteria -- Indie hackers -- Solo founders -- Small product teams -- Buyers who have already picked a GitHub project but need it running +The fork is moving in the right direction when one content unit can lead to multiple assets: -Primary monetization order: +1. short-form content +2. written content +3. owned capture point +4. monetization path -1. Deployment / hardening / customization services -2. Content as proof and lead generation -3. Outreach to accelerate conversations -4. Affiliate / info product / productized templates later +The fork is drifting off course when outputs only support: -## Phase 1: Proof-Driven Messaging +- more outreach +- more direct custom work +- more manual selling with no asset accumulation -- [x] Replace generic fork positioning in the README -- [x] Define the fork's specialized business thesis -- [x] Add a dedicated strategy document for Frank's version -- [x] Add a roadmap that prevents future drift -- [ ] Write the final service-page copy for `fzhang.dev` -- [ ] Pick one public offer as the single CTA for all channels +## Monetization Stack -## Phase 2: Content Engine Refactor +### Layer 1: Owned Attention -- [x] Add account-level service content profiles -- [x] Make YouTube topic generation case-study oriented -- [x] Make YouTube scripts attract qualified prospects instead of generic viewers -- [x] Make metadata and descriptions include soft service CTAs -- [x] Make X posts calm, practical, and problem-solution driven -- [x] Add support for loading reusable case briefs from files -- [x] Add a review step before publishing generated content -- [x] Add content variants for `deployment`, `hardening`, and `customization` +- newsletter signups +- RSS / subscription growth +- bookmarkable site content -## Phase 3: Offer Packaging +### Layer 2: Utility Assets -- [ ] Define 3 standard offers: -- [ ] `Deployment Sprint` -- [ ] `Hardening Pass` -- [ ] `Customization Sprint` -- [ ] Document delivery boundaries, inputs, outputs, and exclusions -- [ ] Add pricing guidance and upgrade path -- [ ] Add templates for discovery notes and project handoff notes +- checklists +- setup guides +- resource packs +- comparison pages +- template pages -## Phase 4: Outreach Engine +### Layer 3: Revenue -- [ ] Rewrite outreach copy around concrete technical outcomes -- [ ] Narrow scraping keywords toward founder / operator / builder intent -- [ ] Add contact qualification notes before sending outreach -- [ ] Track reply quality, booked calls, and converted deals -- [ ] Build one outreach flow per offer instead of generic cold email +- affiliate links where trust is earned +- paid SOPs +- paid template packs +- low-touch diagnostic or audit offers -## Phase 5: Proof Asset Library +### Layer 4: Bootstrap Revenue -- [ ] Publish 3 public case studies -- [ ] Publish 10 short-form technical proof posts -- [ ] Publish 3 longer articles on `fzhang.dev` -- [ ] Build a reusable before/after screenshot library -- [ ] Maintain a list of real problems solved, grouped by offer +- selective productized service work -## Phase 6: Productization +This layer is allowed, but it should finance the earlier layers rather than dominate the system. -- [ ] Turn repeatable deployment patterns into checklists -- [ ] Turn hardening steps into reusable audits -- [ ] Turn recurring setup work into packaged templates -- [ ] Evaluate a paid knowledge product or starter kit -- [ ] Evaluate selective affiliate recommendations only after proof exists +## Phase 1: Thesis Reset + +- [x] Rewrite the fork strategy around asset compounding +- [x] Rewrite the roadmap around owned audience and reusable assets +- [ ] Remove or reframe old service-led messaging where it creates strategic confusion +- [ ] Define the first primary asset type this fork will print + +## Phase 2: Intent-Driven Content Engine + +- [ ] Replace broad service-led prompts with monetizable-intent prompts +- [ ] Create content variants for: +- [ ] deployment intent +- [ ] risk / hardening intent +- [ ] tool comparison intent +- [ ] cost / trade-off intent +- [ ] affiliate-safe recommendation intent +- [ ] Add topic scoring based on searchability, evergreen value, and conversion potential + +## Phase 3: Asset Expansion Pipeline + +- [ ] Turn one topic into short + post + article + capture hook +- [ ] Add support for article-outline generation from the same brief +- [ ] Add support for downloadable asset hooks such as checklists or templates +- [ ] Create reusable asset-brief templates instead of only case-study briefs + +## Phase 4: Owned Capture + +- [ ] Define one primary capture target: +- [ ] newsletter +- [ ] free resource pack +- [ ] checklist download +- [ ] waiting list for paid resources +- [ ] Add CTA variants that point to owned capture instead of direct call booking +- [ ] Add measurement for capture conversion by topic type + +## Phase 5: Monetization Experiments + +- [ ] Define the first affiliate-safe topic cluster +- [ ] Define the first paid digital asset to test +- [ ] Define the first low-touch offer, only if needed as bootstrap revenue +- [ ] Map which content types should lead to which monetization type + +## Phase 6: Site Integration + +- [ ] Keep `fzhang.dev` primarily as a content site +- [ ] Add a lightweight conversion path from homepage to owned assets +- [ ] Add dedicated pages for resources, comparisons, or templates +- [ ] Avoid turning the whole site into a generic service homepage + +## Phase 7: Measurement + +- [ ] Track which topics produce: +- [ ] clicks +- [ ] subscribers +- [ ] saved resources +- [ ] affiliate conversions +- [ ] product interest +- [ ] optional service conversations +- [ ] Maintain a topic ledger of outputs vs downstream value ## Decision Filters Before adding any new feature, ask: -1. Does this make it easier to win deployment / hardening / customization clients? -2. Does this create public proof of real technical work? -3. Does this reduce delivery friction or improve reuse? -4. If the answer is "no", it is probably off-strategy for this fork. +1. Does this create or improve a reusable asset? +2. Does this help convert rented reach into owned audience? +3. Does this improve future monetization with less manual work? +4. If it mainly helps sell more hours, is it still worth building here? + +If the answer to 1-3 is "no", it is probably off-strategy. ## Execution Guardrails -- Keep one primary offer active at a time. Do not let the repo generate content for multiple unrelated services in parallel. -- Keep content tied to real delivery evidence. Do not manufacture authority with generic AI opinions. -- Treat security claims conservatively. "Basic hardening" is easier to defend than broad "security expert" positioning. -- Prefer sanitized case studies over abstract promises. -- Review generated assets before publishing, especially CTAs, technical claims, and screenshots. -- Protect working capital: prefer activities that shorten the path to the next paid conversation. +- Do not let the repo become "another freelance channel manager". +- Do not force every visitor into a service CTA. +- Do not build around hot takes when evergreen intent is available. +- Do not overfit to one platform's algorithm; prefer portable assets. +- Do not confuse traffic with durable value. +- Do not ship content that has no plausible owned-capture or monetization path. ## Immediate Next Tasks -- [ ] Create one YouTube account and one X account using the new service-led profile fields -- [ ] Define a single target customer and one offer name -- [ ] Create 3 content angles from real delivery experience -- [ ] Publish one short, one X post, and one site article from the same proof asset +- [ ] Choose the first asset type to optimize for: +- [ ] newsletter growth +- [ ] affiliate content +- [ ] resource packs +- [ ] paid templates / SOPs +- [ ] Rewrite the current account profile system around asset destination, not only service offer +- [ ] Draft the first 10 topic angles with monetizable intent +- [ ] Define one homepage conversion block for `fzhang.dev` that points to an owned asset +- [ ] Create one pilot downloadable asset and one article that leads into it - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow From db829118af4b3722b66db954f907c9d048c3876d Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:42:05 +0800 Subject: [PATCH 07/27] Align content engine with first asset strategy --- README.md | 2 +- docs/FinancialFreedomPath.md | 242 +++++++++++++++++++++++++++++++++++ docs/FirstAssetSpec.md | 95 ++++++++++++++ docs/FrankMoneyPrinter.md | 22 ++++ docs/FzhangHomepageCopy.md | 11 +- docs/Roadmap.md | 10 +- src/classes/Twitter.py | 36 +++++- src/classes/YouTube.py | 58 +++++++-- src/content_profile.py | 20 ++- src/main.py | 24 +++- 10 files changed, 484 insertions(+), 36 deletions(-) create mode 100644 docs/FinancialFreedomPath.md create mode 100644 docs/FirstAssetSpec.md diff --git a/README.md b/README.md index 35ad02198..079d57766 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ This fork is being re-optimized around long-term monetizable assets: - direct attention toward assets such as newsletters, resource packs, templates, and selective affiliate offers - treat service revenue as optional bootstrap fuel, not the end state -See [docs/FrankMoneyPrinter.md](docs/FrankMoneyPrinter.md) for the specialization strategy and [docs/Roadmap.md](docs/Roadmap.md) for the implementation phases. +See [docs/FrankMoneyPrinter.md](docs/FrankMoneyPrinter.md) for the specialization strategy, [docs/FinancialFreedomPath.md](docs/FinancialFreedomPath.md) for the staged monetization path, [docs/FirstAssetSpec.md](docs/FirstAssetSpec.md) for the first asset decision, and [docs/Roadmap.md](docs/Roadmap.md) for the implementation phases. ## Versions diff --git a/docs/FinancialFreedomPath.md b/docs/FinancialFreedomPath.md new file mode 100644 index 000000000..08fe95d30 --- /dev/null +++ b/docs/FinancialFreedomPath.md @@ -0,0 +1,242 @@ +# Frank Financial Freedom Path + +This document narrows the long-term goal into staged, testable money types. + +## Final Goal + +Use a one-person company and personal IP to build toward financial freedom. + +That means the business should gradually shift from: + +- selling time + +to: + +- selling reusable systems +- owning audience +- owning monetizable assets + +## The First Money To Print + +After reviewing Frank's personal situation, writing strengths, current site shape, knowledge-base strategy, and aversion to shallow high-volume content, the best first money is: + +> Free resource capture now, followed by paid SOPs and templates later. + +This should come before: + +- pure affiliate-first strategy +- newsletter-first strategy without a concrete resource +- broad productized service expansion + +## Why This Is The Best First Money + +### Fit with strengths + +- strong written expression +- deep technical reflection +- ability to turn messy problems into structured guidance +- habit of documenting and organizing + +### Lower mismatch + +It does not rely on: + +- high-energy daily social performance +- aggressive outreach +- constant live selling +- entertainment-style short-form content + +### Strong bridge + +It creates a bridge between: + +- current knowledge and real experience +- future newsletter growth +- future affiliate pages +- future paid digital assets + +## Stage Model + +### Stage 1: Free Resource Printer + +Goal: + +- convert content attention into owned audience + +Primary output: + +- downloadable checklist +- quick reference sheet +- starter toolkit + +Examples: + +- Open-source AI deployment checklist +- Self-hosted project risk checklist +- Independent builder AI tool stack checklist + +Primary CTA: + +- subscribe +- download + +### Stage 2: Paid SOP / Template Printer + +Goal: + +- sell low-touch digital products built from repeated knowledge patterns + +Primary output: + +- SOP packs +- deployment templates +- setup guides +- reusable prompts / workflows + +Examples: + +- OpenClaw deployment and hardening SOP +- Self-hosted AI project launch checklist pack +- AI workflow setup template pack + +### Stage 3: Affiliate / Comparison Asset Printer + +Goal: + +- turn high-intent search and recommendation content into recurring low-touch revenue + +Primary output: + +- comparison pages +- setup guides +- tool recommendation pages + +Examples: + +- Which tools are worth paying for vs self-hosting +- X vs Y for builders who need Z + +### Stage 4: Optional Bootstrap Service Layer + +Goal: + +- fund the earlier stages without letting service work dominate strategy + +Allowed outputs: + +- low-touch diagnostic +- narrowly scoped productized implementation + +This exists to support asset building, not replace it. + +## Why Not Start With Pure Affiliate + +- requires stronger existing traffic +- easier to become generic +- easier to lose trust if recommendations outrun proof + +## Why Not Start With Pure Newsletter + +- too abstract without a reason to subscribe +- weaker conversion when no concrete downloadable value exists + +## Why Not Start With Broad Service Packages + +- drifts back into selling time +- weakens the "printer" logic +- too easy to become another freelance channel + +## Definitions + +### Lead Magnet + +A small free asset offered in exchange for a relationship or next step. + +Examples: + +- checklist +- quick audit sheet +- starter template +- short PDF guide + +Its job is not to make money directly. +Its job is to capture intent and move a reader into owned audience. + +### Long-tail Content + +Content built around specific, repeated search intent rather than short-lived trends. + +Examples: + +- how to deploy X +- why Y breaks after setup +- X vs Y for a specific workflow + +Its job is to keep attracting discoverable traffic over time. + +### Affiliate-safe Topic + +A topic where recommending a tool or product feels natural, useful, and trust-preserving. + +Good examples: + +- deployment stack choices +- hosting trade-offs +- security tool comparisons + +Bad examples: + +- random product pushing with no real use case + +### Download Page + +A dedicated page whose only purpose is to explain and deliver a free or paid asset. + +Example contents: + +- what the asset is +- who it is for +- what problem it solves +- how to get it + +### Conversion Action + +The next step you want the reader to take. + +Good conversion actions at this stage: + +- subscribe +- download +- join waitlist +- click comparison page + +Weaker default action at this stage: + +- book a call + +## First 90-Day Focus + +### Month 1 + +- choose one resource asset +- build one download page +- create 5-10 content angles that feed into it + +### Month 2 + +- publish content consistently +- capture subscribers / downloads +- measure which topic types attract the right audience + +### Month 3 + +- expand the best-performing resource into a paid SOP or template concept +- test whether users want the deeper version + +## Guiding Rule + +If a new action does not improve one of these three things, be skeptical: + +1. owned audience +2. reusable content assets +3. low-touch monetization diff --git a/docs/FirstAssetSpec.md b/docs/FirstAssetSpec.md new file mode 100644 index 000000000..5203f80f9 --- /dev/null +++ b/docs/FirstAssetSpec.md @@ -0,0 +1,95 @@ +# First Asset Spec + +## Decision + +The first asset should be: + +> A free checklist for builders who are trying to deploy or self-host an open-source AI / Web project. + +Recommended working title: + +- `开源 AI 项目部署前检查清单` + +## Why This Asset + +- easy to understand +- narrow enough to finish +- broad enough to attract the right audience +- naturally leads into deeper SOPs and templates +- aligned with Frank's documented strengths in structured explanation and technical risk awareness + +## Audience + +- independent developers +- small teams +- founders trying to self-host or deploy open-source tools +- builders who picked a repo but are worried about setup mistakes + +## Problem It Solves + +Before deployment, many people do not know: + +- what to check +- what can break later +- what is safe to postpone +- what must be decided before launch + +The checklist reduces random trial-and-error and helps readers feel: + +- more prepared +- more systematic +- more likely to succeed + +## Asset Format + +Version 1: + +- one downloadable markdown or PDF checklist +- one landing / download page +- one short-form content cluster feeding into it + +## Example Sections + +- repo readiness +- environment variables +- domain / HTTPS +- database / storage choices +- auth / exposure decisions +- backup / rollback basics +- logging / observability basics +- what to verify before going public + +## CTA + +Primary CTA: + +- `领取免费清单` + +Secondary CTA: + +- `订阅后续更新` + +## Stage 2 Product + +This free asset should later expand into a paid asset. + +Recommended second-stage paid asset: + +- `开源 AI 项目上线与基础加固 SOP` + +Possible paid formats: + +- SOP pack +- step-by-step launch playbook +- template bundle + +## What The Free Asset Should Lead To + +Free checklist -> subscriber / downloader -> trust -> paid SOP or template -> optional affiliate / low-touch offer later + +## What To Avoid + +- do not make the free asset too broad +- do not make it generic "AI productivity tips" +- do not turn it into a sales brochure +- do not require heavy customization to feel useful diff --git a/docs/FrankMoneyPrinter.md b/docs/FrankMoneyPrinter.md index 7c85000d7..f78ebf393 100644 --- a/docs/FrankMoneyPrinter.md +++ b/docs/FrankMoneyPrinter.md @@ -247,3 +247,25 @@ If the answer to 1-3 is "no", be skeptical. For Frank, `MoneyPrinterV2` should become: > A content-asset production and distribution system that compounds into owned audience, monetizable pages, and low-touch revenue streams. + +## Current First Bet + +The first concrete bet is no longer open-ended. + +The fork should optimize first for: + +- free resource capture +- then paid SOPs / templates + +This is a better match than: + +- affiliate-first +- service-first +- newsletter-without-asset-first + +because it fits the current strengths: + +- structured thinking +- written explanation +- technical documentation +- repeatable process extraction diff --git a/docs/FzhangHomepageCopy.md b/docs/FzhangHomepageCopy.md index c7acd46ea..b5136f01e 100644 --- a/docs/FzhangHomepageCopy.md +++ b/docs/FzhangHomepageCopy.md @@ -25,8 +25,7 @@ Primary job: Recommended primary action: -- `订阅更新` -- or `领取一份免费资源` +- `领取一份免费资源` Recommended secondary action: @@ -79,9 +78,9 @@ Add one lightweight block below the hero and above recent posts. ### CTA options -- Primary: `订阅更新` +- Primary: `领取免费清单` - Secondary: `查看文章归档` -- Optional: `领取免费清单` +- Optional: `订阅更新` ## Stronger Version If You Want One Resource CTA @@ -147,9 +146,9 @@ That keeps the site aligned with the new MoneyPrinter direction: ## Recommended Homepage CTA Hierarchy -1. `订阅更新` +1. `领取免费清单` 2. `查看文章归档` -3. `领取免费清单` or `了解更多` +3. `订阅更新` or `了解更多` 4. optional service link, but not primary ## Meta Direction diff --git a/docs/Roadmap.md b/docs/Roadmap.md index ccc265684..e5f34415c 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -65,7 +65,7 @@ This layer is allowed, but it should finance the earlier layers rather than domi - [x] Rewrite the fork strategy around asset compounding - [x] Rewrite the roadmap around owned audience and reusable assets - [ ] Remove or reframe old service-led messaging where it creates strategic confusion -- [ ] Define the first primary asset type this fork will print +- [x] Define the first primary asset type this fork will print ## Phase 2: Intent-Driven Content Engine @@ -142,14 +142,12 @@ If the answer to 1-3 is "no", it is probably off-strategy. ## Immediate Next Tasks -- [ ] Choose the first asset type to optimize for: -- [ ] newsletter growth -- [ ] affiliate content -- [ ] resource packs -- [ ] paid templates / SOPs +- [x] Choose the first asset type to optimize for: free resource capture first, paid SOP/template second - [ ] Rewrite the current account profile system around asset destination, not only service offer - [ ] Draft the first 10 topic angles with monetizable intent +- [ ] Define the first lead magnet - [ ] Define one homepage conversion block for `fzhang.dev` that points to an owned asset - [ ] Create one pilot downloadable asset and one article that leads into it +- [ ] Design the second-stage paid SOP/template that the lead magnet should eventually feed into - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow diff --git a/src/classes/Twitter.py b/src/classes/Twitter.py index 362578c95..a87d04aaa 100644 --- a/src/classes/Twitter.py +++ b/src/classes/Twitter.py @@ -56,7 +56,25 @@ def _variant_instruction(self) -> str: ) return ( - "Focus on practical implementation lessons that can lead into deployment, hardening, or customization work." + "Focus on practical implementation lessons that can become reusable content, downloadable resources, or low-touch monetizable assets." + ) + + def _asset_instruction(self) -> str: + """ + Returns specialized guidance for the selected asset type. + + Returns: + instruction (str): Asset-specific prompt guidance + """ + asset_type = self.content_profile.get("asset_type", "") + capture_type = self.content_profile.get("capture_type", "") + monetization_type = self.content_profile.get("monetization_type", "") + + return ( + f"Primary asset type: {asset_type or 'general content asset'}. " + f"Capture type: {capture_type or 'none'}. " + f"Monetization type: {monetization_type or 'none'}. " + "The post should nudge the reader toward a reusable asset or owned relationship, not only a direct service sale." ) def __init__( @@ -245,7 +263,7 @@ def generate_post(self) -> str: if has_service_strategy(self.content_profile): completion = generate_text( f""" - Write a concise X post in {get_twitter_language()} for a technical service business. + Write a concise X post in {get_twitter_language()} for a technical content and audience-building business. Topic / angle: {self.topic} {build_profile_context(self.content_profile)} @@ -253,13 +271,16 @@ def generate_post(self) -> str: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Requirements: - Maximum 240 characters - Sound like a calm operator, not a hype marketer - - Mention one concrete problem, one practical insight, and optionally a soft CTA - - Prefer deployment, security, workflow, or implementation lessons - - Avoid generic inspiration and vague AI hot takes + - Mention one concrete problem and one practical insight + - Prefer deployment, security, workflow, cost, or implementation lessons + - Avoid generic inspiration, vague AI hot takes, and empty engagement bait + - If there is a CTA, point to a reusable asset, subscription, download, or owned destination before direct selling - Only return the post text """ ) @@ -301,7 +322,7 @@ def review_post(self, draft: str) -> str: """ reviewed = generate_text( f""" - Review and improve this X post for a technical service operator. + Review and improve this X post for a technical asset-building operator. Draft: {draft} @@ -313,11 +334,14 @@ def review_post(self, draft: str) -> str: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Requirements: - Keep the core meaning - Remove hype, fluff, and generic AI phrasing - Make it sound specific, credible, and useful + - Prefer owned-audience or reusable-asset direction over hard selling - Keep it under 240 characters - Only return the final post """ diff --git a/src/classes/YouTube.py b/src/classes/YouTube.py index e0b20efde..f169adb74 100644 --- a/src/classes/YouTube.py +++ b/src/classes/YouTube.py @@ -76,7 +76,27 @@ def _variant_instruction(self) -> str: ) return ( - "Emphasize concrete implementation lessons that can naturally lead into deployment, hardening, or customization work." + "Emphasize concrete implementation lessons that can naturally lead into reusable content assets, downloadable resources, or low-touch monetization." + ) + + def _asset_instruction(self) -> str: + """ + Returns specialized guidance for the selected asset destination. + + Returns: + instruction (str): Asset-specific prompt guidance + """ + asset_type = self.content_profile.get("asset_type", "") + capture_type = self.content_profile.get("capture_type", "") + monetization_type = self.content_profile.get("monetization_type", "") + asset_name = self.content_profile.get("asset_name", "") + + return ( + f"Primary asset type: {asset_type or 'general content asset'}. " + f"Capture type: {capture_type or 'none'}. " + f"Monetization type: {monetization_type or 'none'}. " + f"Asset name: {asset_name or 'none'}. " + "The video should help build reusable audience and asset value before pushing direct services." ) def __init__( @@ -176,7 +196,7 @@ def generate_topic(self) -> str: if has_service_strategy(self.content_profile): completion = self.generate_response( f""" - You are planning a short-form educational video that attracts qualified leads to a technical service. + You are planning a short-form educational video that grows durable content assets and owned audience around technical workflows. Domain / niche: {self.niche} Language: {self.language} @@ -185,14 +205,16 @@ def generate_topic(self) -> str: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Generate one concrete short-video angle in exactly one sentence. Requirements: - - Make it practical, credibility-first, and case-study oriented. - - Prefer deployment lessons, security pitfalls, implementation trade-offs, or client-facing outcomes. + - Make it practical, credibility-first, and useful enough to support long-tail discovery. + - Prefer deployment lessons, security pitfalls, implementation trade-offs, cost trade-offs, or reusable workflow outcomes. - Avoid vague motivation, generic AI news, and broad listicles. - - The angle should feel like something a founder or small team would actually click because it solves a real problem. + - The angle should feel like something a builder would search, save, or subscribe for. - Only return the topic sentence. """ ) @@ -228,17 +250,19 @@ def generate_script(self) -> str: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Script goals: - - Attract the right prospect, not broad entertainment traffic. + - Attract the right reader/viewer, not broad entertainment traffic. - Sound like a calm technical operator explaining a real-world lesson. - - Make the audience feel "this person can probably solve my problem". + - Make the audience feel "this is worth saving or subscribing for". Structure: - Sentence 1: Name a concrete problem, failure mode, or costly mistake. - Sentence 2: Explain why it happens or what most people miss. - Sentence 3: Show the practical fix, principle, or workflow. - - Sentence 4: Describe the business/technical outcome or a soft CTA. + - Sentence 4: Describe the reusable outcome, next step, or soft asset CTA. Rules: - No markdown, no title, no bullet points. @@ -309,12 +333,15 @@ def generate_metadata(self) -> dict: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Requirements: - Under 90 characters - Specific and useful, not clickbait - May use 1-2 targeted hashtags if they help - Should signal a real deployment, security, automation, or implementation lesson + - Prefer searchable clarity over generic persuasion - Only return the title """ ) @@ -341,12 +368,14 @@ def generate_metadata(self) -> dict: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Requirements: - Summarize the lesson in 2-4 short lines - Sound practical and trustworthy - Mention the target outcome for the audience - - Include a soft CTA to contact or learn more + - Include a soft CTA to subscribe, download, or learn more - If a CTA URL is present in the context, include it naturally - Only return the description """ @@ -384,12 +413,14 @@ def generate_prompts(self) -> List[str]: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Visual direction: - product UI mockups - terminal / dashboard / architecture visuals - secure infrastructure scenes - - founder workflow, deployment workflow, before/after states + - workflow diagrams, checklists, resource-pack style visuals - realistic modern SaaS or engineering imagery Rules: @@ -490,12 +521,14 @@ def review_script(self, draft: str) -> str: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Requirements: - Keep it concise and practical - Remove hype, filler, and vague wording - Keep the tone calm and operator-like - - Make the value to the prospect obvious + - Make the reusable value to the reader obvious - Only return the final script """ ) @@ -528,6 +561,8 @@ def review_metadata(self, draft_metadata: dict) -> dict: {self.case_brief or "None"} Variant guidance: {self._variant_instruction()} + Asset guidance: + {self._asset_instruction()} Return valid JSON only with this schema: {{ @@ -539,6 +574,7 @@ def review_metadata(self, draft_metadata: dict) -> dict: - Specific, credible, no hype - Keep title under 90 characters - Keep description concise and CTA-aware + - Prefer owned asset capture over direct service selling """ ) diff --git a/src/content_profile.py b/src/content_profile.py index 55e0bf154..2530c08ea 100644 --- a/src/content_profile.py +++ b/src/content_profile.py @@ -45,8 +45,12 @@ def normalize_content_profile(content_profile: dict | None) -> dict: profile = { "content_mode": str(raw.get("content_mode", "") or "").strip().lower(), "content_variant": str(raw.get("content_variant", "") or "").strip().lower(), + "asset_type": str(raw.get("asset_type", "") or "").strip().lower(), + "capture_type": str(raw.get("capture_type", "") or "").strip().lower(), + "monetization_type": str(raw.get("monetization_type", "") or "").strip().lower(), "target_customer": str(raw.get("target_customer", "") or "").strip(), "offer_name": str(raw.get("offer_name", "") or "").strip(), + "asset_name": str(raw.get("asset_name", "") or "").strip(), "primary_problem": str(raw.get("primary_problem", "") or "").strip(), "desired_outcome": str(raw.get("desired_outcome", "") or "").strip(), "cta_url": str(raw.get("cta_url", "") or "").strip(), @@ -61,6 +65,10 @@ def normalize_content_profile(content_profile: dict | None) -> dict: [ profile["target_customer"], profile["offer_name"], + profile["asset_type"], + profile["capture_type"], + profile["monetization_type"], + profile["asset_name"], profile["primary_problem"], profile["desired_outcome"], profile["cta_url"], @@ -70,7 +78,7 @@ def normalize_content_profile(content_profile: dict | None) -> dict: profile["content_pillars"], ] ) - profile["content_mode"] = "service_case_study" if has_strategy_data else "legacy" + profile["content_mode"] = "asset_printer" if has_strategy_data else "legacy" if not profile["content_variant"]: profile["content_variant"] = "general" @@ -89,7 +97,7 @@ def has_service_strategy(content_profile: dict | None) -> bool: enabled (bool): True when service-led prompts should be used """ profile = normalize_content_profile(content_profile) - return profile["content_mode"] == "service_case_study" + return profile["content_mode"] in {"service_case_study", "asset_printer"} def build_profile_context(content_profile: dict | None) -> str: @@ -109,8 +117,16 @@ def build_profile_context(content_profile: dict | None) -> str: lines.append(f"Target customer: {profile['target_customer']}") if profile["content_variant"]: lines.append(f"Content variant: {profile['content_variant']}") + if profile["asset_type"]: + lines.append(f"Primary asset type: {profile['asset_type']}") + if profile["capture_type"]: + lines.append(f"Capture type: {profile['capture_type']}") + if profile["monetization_type"]: + lines.append(f"Monetization type: {profile['monetization_type']}") if profile["offer_name"]: lines.append(f"Offer: {profile['offer_name']}") + if profile["asset_name"]: + lines.append(f"Asset name: {profile['asset_name']}") if profile["primary_problem"]: lines.append(f"Primary problem solved: {profile['primary_problem']}") if profile["desired_outcome"]: diff --git a/src/main.py b/src/main.py index 1edf5acc2..54902786f 100644 --- a/src/main.py +++ b/src/main.py @@ -35,7 +35,7 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: False, ) use_strategy = question( - " => Use personalized case-study content prompts? (Yes/No, default Yes): " + " => Use personalized asset-led content prompts? (Yes/No, default Yes): " ).strip().lower() if use_strategy in {"no", "n"}: @@ -45,10 +45,22 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: " => Target customer (e.g. indie hackers, founders, small teams): " ).strip() content_variant = question( - " => Content variant (deployment/hardening/customization/general): " + " => Content variant (deployment/hardening/comparison/cost/general): " ).strip().lower() + asset_type = question( + " => Primary asset type (newsletter/checklist/template/sop/affiliate/article): " + ).strip().lower() + capture_type = question( + " => Capture type (subscribe/download/waitlist/clickthrough/none): " + ).strip().lower() + monetization_type = question( + " => Monetization type (paid_template/paid_sop/affiliate/low_touch_service/none): " + ).strip().lower() + asset_name = question( + f" => Asset name for this {account_type} account (optional): " + ).strip() offer_name = question( - f" => Main offer promoted by this {account_type} account: " + f" => Optional supporting offer promoted by this {account_type} account: " ).strip() primary_problem = question(" => Main problem you solve for them: ").strip() desired_outcome = question(" => Desired customer outcome: ").strip() @@ -67,10 +79,14 @@ def prompt_content_profile(default_topic: str, account_type: str) -> dict: ).strip() return { - "content_mode": "service_case_study", + "content_mode": "asset_printer", "content_variant": content_variant or "general", + "asset_type": asset_type, + "capture_type": capture_type, + "monetization_type": monetization_type, "target_customer": target_customer, "offer_name": offer_name, + "asset_name": asset_name, "primary_problem": primary_problem, "desired_outcome": desired_outcome, "cta_url": cta_url, From bad6522de8adc34197d4fcc36cfb04dfb84dd8d7 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:59:21 +0800 Subject: [PATCH 08/27] Build first asset and monetizable topic path --- docs/Roadmap.md | 12 +- docs/assets/First10LongTailTopics.md | 131 ++++++++++++++++++ .../assets/OpenSourceAIDeploymentChecklist.md | 105 ++++++++++++++ ...nSourceAIDeploymentChecklistLandingPage.md | 76 ++++++++++ docs/assets/README.md | 12 ++ 5 files changed, 330 insertions(+), 6 deletions(-) create mode 100644 docs/assets/First10LongTailTopics.md create mode 100644 docs/assets/OpenSourceAIDeploymentChecklist.md create mode 100644 docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md create mode 100644 docs/assets/README.md diff --git a/docs/Roadmap.md b/docs/Roadmap.md index e5f34415c..28b0275ee 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -69,7 +69,7 @@ This layer is allowed, but it should finance the earlier layers rather than domi ## Phase 2: Intent-Driven Content Engine -- [ ] Replace broad service-led prompts with monetizable-intent prompts +- [x] Replace broad service-led prompts with monetizable-intent prompts - [ ] Create content variants for: - [ ] deployment intent - [ ] risk / hardening intent @@ -143,11 +143,11 @@ If the answer to 1-3 is "no", it is probably off-strategy. ## Immediate Next Tasks - [x] Choose the first asset type to optimize for: free resource capture first, paid SOP/template second -- [ ] Rewrite the current account profile system around asset destination, not only service offer -- [ ] Draft the first 10 topic angles with monetizable intent -- [ ] Define the first lead magnet +- [x] Rewrite the current account profile system around asset destination, not only service offer +- [x] Draft the first 10 topic angles with monetizable intent +- [x] Define the first lead magnet - [ ] Define one homepage conversion block for `fzhang.dev` that points to an owned asset -- [ ] Create one pilot downloadable asset and one article that leads into it -- [ ] Design the second-stage paid SOP/template that the lead magnet should eventually feed into +- [x] Create one pilot downloadable asset draft +- [x] Design the second-stage paid SOP/template that the lead magnet should eventually feed into - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow diff --git a/docs/assets/First10LongTailTopics.md b/docs/assets/First10LongTailTopics.md new file mode 100644 index 000000000..4f716eb29 --- /dev/null +++ b/docs/assets/First10LongTailTopics.md @@ -0,0 +1,131 @@ +# First 10 Long-Tail Topics + +These topics are designed to feed the first lead magnet: + +> 开源 AI 项目部署前检查清单 + +Each topic should naturally point to: + +- the free checklist +- the site as a long-term technical resource +- future SOP / template monetization + +## 1. 为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? + +Intent: + +- high + +Why it fits: + +- directly tied to deployment pain +- easy to connect to checklist CTA + +## 2. 部署一个 GitHub 项目前,最应该先确认的 10 件事 + +Intent: + +- very high + +Why it fits: + +- nearly identical to the lead magnet topic +- strong search and conversion intent + +## 3. 开源项目值不值得部署,应该先看 README 里的哪些信号? + +Intent: + +- high + +Why it fits: + +- helps users filter before wasting time +- positions you as a judgment layer, not just a tool user + +## 4. 自部署 AI / Web 项目时,哪些环境变量问题最容易把人拖死? + +Intent: + +- high + +Why it fits: + +- concrete +- technical +- naturally extends into SOP later + +## 5. 为什么很多项目死在“能启动”,却没有死在“能上线”? + +Intent: + +- medium to high + +Why it fits: + +- strong framing article +- good for thought leadership with practical edge + +## 6. 开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? + +Intent: + +- very high + +Why it fits: + +- directly supports checklist and later paid SOP + +## 7. 自部署项目时,什么时候应该自己折腾,什么时候应该直接换方案? + +Intent: + +- high + +Why it fits: + +- reflects your judgment strength +- can support future affiliate-safe recommendations + +## 8. 域名、HTTPS、反代、鉴权:开源项目第一次公开上线前最容易漏掉什么? + +Intent: + +- high + +Why it fits: + +- operational +- practical +- useful as a standalone checklist teaser + +## 9. 一个项目“看起来很强”不等于“值得你真的部署” + +Intent: + +- medium + +Why it fits: + +- strong opinion piece +- useful for attracting the right audience + +## 10. 如果今天让我从零开始部署一个开源 AI 项目,我会先做哪几步? + +Intent: + +- high + +Why it fits: + +- approachable +- personal +- good bridge between blog voice and reusable framework + +## Suggested Rollout Order + +1. 部署一个 GitHub 项目前,最应该先确认的 10 件事 +2. 为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? +3. 开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? +4. 域名、HTTPS、反代、鉴权:开源项目第一次公开上线前最容易漏掉什么? +5. 一个项目“看起来很强”不等于“值得你真的部署” diff --git a/docs/assets/OpenSourceAIDeploymentChecklist.md b/docs/assets/OpenSourceAIDeploymentChecklist.md new file mode 100644 index 000000000..4f7fddbdc --- /dev/null +++ b/docs/assets/OpenSourceAIDeploymentChecklist.md @@ -0,0 +1,105 @@ +# 开源 AI 项目部署前检查清单 + +适用对象: + +- 想把 GitHub 上的开源 AI / Web 项目真正跑起来的人 +- 独立开发者、小团队、个人创业者 +- 已经挑好了项目,但担心部署踩坑、上线后不稳或后续难维护的人 + +这份清单的目标不是让你“一次就做得完美”,而是帮你在开始部署前,把最容易忽略、但后面最容易出问题的关键项先过一遍。 + +## 一、项目本身值不值得部署 + +- [ ] 我能用一句话说清楚这个项目要解决什么问题 +- [ ] 我知道这个项目服务的是谁,而不是只觉得“看起来很强” +- [ ] 我确认这个项目不是已经停止维护太久的废弃仓库 +- [ ] 我看过 README、安装文档、issues、最近提交记录 +- [ ] 我知道这个项目更适合 `本地使用`、`内网使用` 还是 `公开上线` +- [ ] 我知道如果它失败了,我的替代方案是什么 + +## 二、部署前的环境准备 + +- [ ] 我知道这个项目需要什么运行环境 +- [ ] 我知道是 `Node / Python / Docker / 数据库 / 反向代理` 中的哪些组合 +- [ ] 我确认本地或服务器的系统版本和依赖版本大致兼容 +- [ ] 我没有一上来就把项目丢进生产环境 +- [ ] 我至少准备了一个可测试环境 + +## 三、配置文件与环境变量 + +- [ ] 我找到了所有必填环境变量 +- [ ] 我知道哪些变量是 API key、哪些是数据库配置、哪些是第三方服务地址 +- [ ] 我没有把真实密钥直接写进代码仓库 +- [ ] 我确认了默认配置里有没有明显不安全的占位值 +- [ ] 我知道哪些变量可以后补,哪些必须在第一次部署前就确定 + +## 四、数据与存储 + +- [ ] 我知道这个项目是否会生成或保存用户数据 +- [ ] 我知道数据存在哪里:本地文件、数据库、对象存储,还是第三方平台 +- [ ] 我知道哪些数据丢失后会很麻烦 +- [ ] 我至少想过一次备份方案 +- [ ] 我知道数据库初始化、迁移、回滚大致怎么做 + +## 五、域名、网络与公开暴露 + +- [ ] 我知道项目最终是内网访问、固定用户访问,还是对公网开放 +- [ ] 如果要公开上线,我知道域名、HTTPS、反向代理要怎么处理 +- [ ] 我不会默认把管理后台、调试接口、测试端点直接暴露到公网 +- [ ] 我确认了端口暴露范围,而不是“能通就行” +- [ ] 我知道如果将来要迁移域名或服务器,大概要改哪些地方 + +## 六、鉴权与基础安全 + +- [ ] 我知道这个项目是否自带登录、权限控制或管理员账户 +- [ ] 我确认默认账号、默认密码、测试密钥有没有被关闭或替换 +- [ ] 我知道哪些页面或接口必须加鉴权 +- [ ] 我没有把“本地能跑”误当成“可以公开上线” +- [ ] 我知道日志、报错信息里会不会泄露密钥、路径或内部结构 + +## 七、运行稳定性 + +- [ ] 我知道项目如何启动、如何重启、如何停止 +- [ ] 我知道如果进程挂了,怎么恢复 +- [ ] 我至少看过一次启动日志和运行日志 +- [ ] 我知道哪些错误是正常告警,哪些是必须立即处理的问题 +- [ ] 我没有把“启动成功一次”误当成“已经稳定” + +## 八、更新与维护成本 + +- [ ] 我知道后续升级可能影响哪些配置 +- [ ] 我知道这个项目是不是会频繁 breaking change +- [ ] 我知道未来继续维护它的人是谁 +- [ ] 我没有选一个“只有现在能跑、以后没人能接手”的方案 +- [ ] 我大致知道这个项目每月可能会消耗什么成本:算力、存储、第三方 API、时间 + +## 九、业务适配 + +- [ ] 我确认这个项目当前版本和我的实际业务流程匹配程度够不够 +- [ ] 我知道哪些地方只是“看着炫”,哪些地方才是真正要改的 +- [ ] 我不会在项目刚跑起来时就急着做所有定制需求 +- [ ] 我能区分“必须先改”和“以后再说” +- [ ] 我知道如果要二次改造,应该优先改哪个环节 + +## 十、上线前最后一轮确认 + +- [ ] 我已经用真实流程走过一遍最关键的操作路径 +- [ ] 我知道最容易出错的三个地方分别是什么 +- [ ] 我知道如果今天必须回滚,应该怎么回 +- [ ] 我没有把“差不多”当成“可以上线” +- [ ] 我清楚这次上线的目标只是“可用第一版”,不是“一步到位” + +## 最后 + +如果你在勾这份清单时,发现自己反复卡在下面这些问题上: + +- 不知道该选哪个项目 +- 不知道该怎么配环境 +- 不知道哪些风险必须先处理 +- 不知道哪些改造可以后面再做 + +那真正的问题通常不是“你不够努力”,而是: + +> 你现在需要的不是继续盲试,而是先把部署逻辑和风险优先级梳理清楚。 + +这也是为什么,很多项目不是死在“不会开发”,而是死在“部署和上线前没有把关键问题先想明白”。 diff --git a/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md b/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md new file mode 100644 index 000000000..7fc12fb28 --- /dev/null +++ b/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md @@ -0,0 +1,76 @@ +# 下载页文案:开源 AI 项目部署前检查清单 + +## 页面目标 + +让读者留下联系方式或完成订阅,领取第一份免费资源。 + +## 页面标题 + +`开源 AI 项目部署前检查清单` + +## 副标题 + +`在你把一个开源 AI / Web 项目真正部署到本地或服务器之前,先用这份清单把最容易被忽略、却最容易在后面变成麻烦的关键项过一遍。` + +## 首屏说明 + +`很多项目不是死在“不会开发”,而是死在“部署前没有把关键问题想明白”。` + +`这份清单适合独立开发者、小团队和个人创业者。它不会教你空泛的“AI 创业建议”,而是帮你在真正动手之前,先把部署、配置、风险和后续维护中最关键的问题梳理清楚。` + +## 你会拿到什么 + +- `一份可直接使用的部署前检查清单` +- `按真实部署流程拆分的关键检查项` +- `从项目是否值得部署,到配置、数据、鉴权、上线前确认的完整结构` +- `适合后续继续延伸成自己的 SOP 或项目准备流程` + +## 这份清单适合谁 + +- `已经选好了 GitHub 项目,但担心一上手就踩坑的人` +- `打算自部署开源 AI / Web 工具的小团队` +- `想把“本地能跑”推进到“第一版可用”的独立开发者` +- `不想继续在环境问题和反复试错上浪费时间的人` + +## 这份清单不适合谁 + +- `只是想看泛泛 AI 热点内容的人` +- `还没有任何项目方向,只想随便收藏资料的人` +- `期待一份清单替代所有技术判断的人` + +## 使用方式 + +`下载后,你可以直接照着勾。` + +`如果你正在评估一个具体项目,这份清单最适合在真正部署前使用;如果你已经开始部署了,也可以反过来用它定位自己目前遗漏了哪些关键环节。` + +## 表单前引导 + +`留下邮箱或订阅方式后,我会把这份清单发给你。` + +`后续如果我把这份清单扩展成更完整的《开源 AI 项目上线与基础加固 SOP》,你也会优先知道。` + +## CTA + +- 主按钮:`领取免费清单` + +## 表单后提示 + +`资源会发送到你留下的联系方式。` + +`如果你后续对“如何从清单走到真正上线”更感兴趣,后续会有更完整的 SOP / 模板版本。` + +## 页面下方补充文案 + +### 为什么先做免费清单,而不是直接卖课或卖服务 + +`因为大多数人现在缺的不是“更宏大的方案”,而是第一份真正能用、能帮他减少试错的结构化资源。` + +`这份清单的意义,不是替你做决定,而是帮你在真正投入时间和成本之前,先把该确认的问题看清楚。` + +### 后续可能扩展的内容 + +- `开源 AI 项目上线与基础加固 SOP` +- `不同部署路径的选择建议` +- `自部署项目常见风险速查表` +- `适合独立开发者的小型工具栈清单` diff --git a/docs/assets/README.md b/docs/assets/README.md new file mode 100644 index 000000000..e0d160dd1 --- /dev/null +++ b/docs/assets/README.md @@ -0,0 +1,12 @@ +# Asset Pack Drafts + +This directory stores early-stage asset drafts for Frank's MoneyPrinter system. + +Current scope: + +- free lead magnets +- download page copy +- first-wave content topic clusters +- future SOP / template drafts + +These files are intentionally written as working assets, not just abstract strategy notes. From c6ed86c74baf63156fd5610a8d0592cd6db078d6 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:48:13 +0800 Subject: [PATCH 09/27] Add first content funnel assets --- docs/Roadmap.md | 11 +- .../Article_DeployGitHubProject10Checks.md | 218 ++++++++++++++++++ ...enSourceAIDeploymentChecklistPostSubmit.md | 70 ++++++ docs/assets/README.md | 3 + .../ShortContent_Pack_DeployChecklist.md | 85 +++++++ 5 files changed, 380 insertions(+), 7 deletions(-) create mode 100644 docs/assets/Article_DeployGitHubProject10Checks.md create mode 100644 docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md create mode 100644 docs/assets/ShortContent_Pack_DeployChecklist.md diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 28b0275ee..e19e3c9ee 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -80,18 +80,14 @@ This layer is allowed, but it should finance the earlier layers rather than domi ## Phase 3: Asset Expansion Pipeline -- [ ] Turn one topic into short + post + article + capture hook +- [x] Turn one topic into short + post + article + capture hook - [ ] Add support for article-outline generation from the same brief -- [ ] Add support for downloadable asset hooks such as checklists or templates +- [x] Add support for downloadable asset hooks such as checklists or templates - [ ] Create reusable asset-brief templates instead of only case-study briefs ## Phase 4: Owned Capture -- [ ] Define one primary capture target: -- [ ] newsletter -- [ ] free resource pack -- [ ] checklist download -- [ ] waiting list for paid resources +- [x] Define one primary capture target: checklist download first - [ ] Add CTA variants that point to owned capture instead of direct call booking - [ ] Add measurement for capture conversion by topic type @@ -148,6 +144,7 @@ If the answer to 1-3 is "no", it is probably off-strategy. - [x] Define the first lead magnet - [ ] Define one homepage conversion block for `fzhang.dev` that points to an owned asset - [x] Create one pilot downloadable asset draft +- [x] Create one pilot article draft and one short-content pack that lead into it - [x] Design the second-stage paid SOP/template that the lead magnet should eventually feed into - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow diff --git a/docs/assets/Article_DeployGitHubProject10Checks.md b/docs/assets/Article_DeployGitHubProject10Checks.md new file mode 100644 index 000000000..b5f84f230 --- /dev/null +++ b/docs/assets/Article_DeployGitHubProject10Checks.md @@ -0,0 +1,218 @@ +# 首发文章:部署一个 GitHub 项目前,最应该先确认的 10 件事 + +## 标题 + +部署一个 GitHub 项目前,最应该先确认的 10 件事 + +## 摘要 + +很多项目不是死在“不会开发”,而是死在“部署前没有把关键问题想明白”。如果你已经挑好了一个开源 AI / Web 项目,这篇文章会帮你在真正动手之前,先确认最容易被忽略、却最容易在后面变成麻烦的 10 个关键点。 + +## 正文 + +很多人看到一个 GitHub 项目,第一反应是: + +- Star 很多 +- 界面很酷 +- 看起来功能挺全 +- 别人都在用 + +然后下一步就是:拉代码、装依赖、改环境变量、开始部署。 + +问题在于,很多项目真正出问题的时候,不是在你第一次 `npm install` 或 `docker compose up` 的那一刻,而是在: + +- 你以为已经能用了,结果一换环境就报错 +- 你以为只是个 demo,结果后来想上线时发现一堆配置根本没想明白 +- 你以为只是先跑跑看,结果数据、鉴权、暴露面、备份全部混在一起 + +所以,如果你已经选好了一个项目,真正值得先做的,不是急着“把它跑起来”,而是先确认下面这 10 件事。 + +## 1. 这个项目到底解决什么问题? + +如果你现在还只能说: + +“这个项目看起来挺强的” + +那大概率说明你还不应该立刻部署它。 + +真正值得部署的项目,至少应该能回答清楚: + +- 它解决的是什么问题? +- 这个问题是不是你现在真的有? +- 你是不是会真的使用它,而不是只是在收藏它? + +很多部署失败,本质上不是技术失败,而是方向失败。 + +## 2. 这个项目更适合本地、内网,还是公网? + +这是最容易被忽略的问题之一。 + +有些项目: + +- 更适合自己本地用 +- 更适合团队内网用 +- 更适合只给少量固定用户访问 + +如果你一开始没想清楚这个问题,后面很多选择都会错位: + +- 是否需要域名 +- 是否需要 HTTPS +- 是否要做鉴权 +- 是否要准备数据库和备份 + +“能跑” 和 “适合公开上线” 根本不是一回事。 + +## 3. 这个仓库的维护状态怎么样? + +不要只看 star。 + +真正该看的通常是: + +- 最近还有没有提交 +- issue 是否长期堆积没人处理 +- README 是否还和当前代码匹配 +- 有没有明显的 breaking change 提示 + +一个看起来很火的项目,也可能已经进入“展示还在,维护基本停掉”的状态。 + +## 4. 你现在用的环境,真的适合它吗? + +很多人一看到项目支持: + +- Node +- Python +- Docker +- PostgreSQL +- Redis + +就直接开始装。 + +但真正会拖死人的,往往是这些细节: + +- 本地和服务器系统版本不一致 +- 文档写的是旧版本依赖 +- 某个基础组件在你的环境里本来就有冲突 +- 本地能跑,不代表换个机器也能跑 + +所以部署前最值得问的一句是: + +> 我现在的环境,真的适合这个项目,还是只是“凑合能试”? + +## 5. 环境变量到底哪些是必须的? + +这是第二个高频坑点。 + +很多项目的 `.env.example` 看起来很多,但你其实不知道: + +- 哪些是真必须 +- 哪些只是可选 +- 哪些是本地测试用 +- 哪些一旦填错,后面会出现非常诡异的问题 + +如果你在部署前不把环境变量梳理一遍,后面几乎一定会进入: + +“明明都填了,为什么还不对?” + +这种状态。 + +## 6. 数据会存在哪里? + +这也是很多人拖到最后才想起来的问题。 + +你至少应该知道: + +- 数据是落本地文件,还是数据库? +- 会不会生成用户数据? +- 会不会需要对象存储? +- 数据丢了以后麻烦大不大? + +如果你连数据落点都没弄清楚,就把项目往服务器上推,后面大概率会在迁移、备份、回滚时被反噬。 + +## 7. 哪些接口或页面不能直接暴露到公网? + +很多项目在本地跑的时候,你不会明显感觉到风险。 + +但一旦公开上线,很多东西就不一样了: + +- 管理后台 +- 调试端点 +- 测试账号 +- 默认密码 +- 没有鉴权的内部页面 + +这些东西本地能开,不代表上线也能开。 + +所以部署前必须问: + +> 哪些页面和端点,只适合我自己看,绝对不该直接暴露出去? + +## 8. 如果项目挂了,你怎么恢复? + +很多人默认认为“以后再说”。 + +但恢复能力不是上线后才考虑的,它应该在上线前就有一个最小答案: + +- 进程挂了怎么重启? +- 数据坏了怎么恢复? +- 配置改错了怎么回滚? + +不需要第一天就把系统做得很完美,但至少不能完全没有想过。 + +## 9. 哪些改造现在必须做,哪些可以以后再做? + +这也是很容易把人拖死的一点。 + +很多项目一跑起来,立刻就会冒出一堆想法: + +- 这里想改 UI +- 那里想接支付 +- 还想加一个工作流 +- 最好再换一个框架 + +问题是,如果你还没把第一版真正跑稳,这些想法大概率只会把项目重新拖回不可控状态。 + +所以更稳的做法是先区分: + +- 必须先改,不然根本不能用 +- 可以以后再改,现在先别动 + +这个区分能力,比“会不会写代码”更重要。 + +## 10. 这次部署的目标到底是什么? + +如果你的目标始终模糊,部署就会不断失控。 + +更好的表述通常是: + +- 先做出可验证的第一版 +- 先让核心路径跑通 +- 先确认这个项目值不值得继续投入 + +而不是: + +- 一次做完整 +- 一次上生产 +- 一次解决所有问题 + +很多项目之所以拖垮人,不是因为难,而是因为一开始就默认自己必须“一步到位”。 + +## 最后 + +如果你现在手上已经有一个想部署的 GitHub 项目,但你发现自己在读这篇文章时不断冒出这些想法: + +- 这个我还真没想过 +- 我现在就卡在这个地方 +- 我本来以为先跑起来再说 + +那说明你现在最需要的,未必是继续盲试,而是先把关键问题过一遍。 + +我把这类最容易被忽略、却最容易在后面出问题的检查项,整理成了一份: + +**《开源 AI 项目部署前检查清单》** + +如果你想在真正动手前,先把部署逻辑和风险优先级梳理清楚,可以先从这份清单开始。 + +## 文末 CTA + +- `领取免费清单` +- `查看相关文章` diff --git a/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md b/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md new file mode 100644 index 000000000..17c932797 --- /dev/null +++ b/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md @@ -0,0 +1,70 @@ +# 免费清单领取后的文案 + +## 提交成功页文案 + +### 标题 + +`清单已经准备好了` + +### 正文 + +`这份《开源 AI 项目部署前检查清单》会发送到你留下的联系方式。` + +`如果你现在正处在“已经选好了项目,但还不确定应该怎么开始部署”的阶段,建议你先完整过一遍这份清单,再决定哪些问题必须现在处理,哪些可以后面再说。` + +### 按钮 + +- `返回首页` +- `先看这篇相关文章` + +相关文章建议链接: + +- `部署一个 GitHub 项目前,最应该先确认的 10 件事` + +## 自动回复 / 邮件文案 + +### 主题 + +`你领取的《开源 AI 项目部署前检查清单》到了` + +### 正文 + +你好, + +这是你领取的 **《开源 AI 项目部署前检查清单》**。 + +这份清单最适合在真正部署一个开源 AI / Web 项目前使用,帮助你先把最容易被忽略、却最容易在后面变成麻烦的关键项过一遍。 + +如果你现在正处在下面这些状态: + +- 已经选好了项目,但还没真正开始部署 +- 已经开始部署,但问题越来越乱 +- 不确定哪些风险必须先处理 + +建议你先按顺序过一遍这份清单,再决定下一步怎么做。 + +后续我还会把这类内容继续扩展成更完整的: + +**《开源 AI 项目上线与基础加固 SOP》** + +如果你更想看系统化、一步步可执行的版本,后续更新会优先发给你。 + +附: +- 免费清单:`(放下载链接或附件)` +- 相关文章:`部署一个 GitHub 项目前,最应该先确认的 10 件事` + +## Thank You 区块文案 + +如果页面支持提交成功后的内嵌推荐区块,可以加这段: + +### 标题 + +`下一步可以看什么` + +### 文案 + +`如果你刚好正在评估一个具体的 GitHub 项目,我建议下一步直接看:` + +- `部署一个 GitHub 项目前,最应该先确认的 10 件事` + +`这篇文章会把“为什么很多项目不是死在开发,而是死在部署前没想明白”讲得更完整。` diff --git a/docs/assets/README.md b/docs/assets/README.md index e0d160dd1..e760e83c4 100644 --- a/docs/assets/README.md +++ b/docs/assets/README.md @@ -6,7 +6,10 @@ Current scope: - free lead magnets - download page copy +- post-submit / follow-up copy +- long-form article drafts - first-wave content topic clusters +- short-form content packs - future SOP / template drafts These files are intentionally written as working assets, not just abstract strategy notes. diff --git a/docs/assets/ShortContent_Pack_DeployChecklist.md b/docs/assets/ShortContent_Pack_DeployChecklist.md new file mode 100644 index 000000000..e31c46d1b --- /dev/null +++ b/docs/assets/ShortContent_Pack_DeployChecklist.md @@ -0,0 +1,85 @@ +# 短内容素材包:开源 AI 项目部署前检查清单 + +## 用途 + +配合以下资产使用: + +- 免费资源:开源 AI 项目部署前检查清单 +- 首发文章:部署一个 GitHub 项目前,最应该先确认的 10 件事 + +## Shorts / Reels 角度 1 + +### 标题 + +`为什么很多 GitHub 项目本地能跑,线上却一塌糊涂?` + +### 脚本 + +很多项目不是死在不会开发,而是死在部署前没把关键问题想明白。你以为本地能跑就差不多了,但一到服务器,环境、配置、鉴权、数据和暴露面全会一起找你麻烦。真正值得先做的,不是盲试,而是先把部署前该确认的事过一遍。 + +### 软 CTA + +`我把这类问题整理成了一份部署前检查清单。` + +## Shorts / Reels 角度 2 + +### 标题 + +`部署一个 GitHub 项目前,最容易漏掉的不是代码` + +### 脚本 + +真正最容易漏掉的,通常是项目值不值得部署、环境变量哪些必须先确认、数据会存哪里、哪些页面绝对不能暴露到公网。很多人一开始就直接拉代码,最后不是卡在配置,就是卡在上线后才发现问题全混在一起。 + +### 软 CTA + +`如果你也在自部署项目,可以先从清单开始。` + +## Shorts / Reels 角度 3 + +### 标题 + +`为什么有些项目一开始就不值得你部署?` + +### 脚本 + +因为 star 多、界面酷、不代表它真的适合你。真正该先看的,是它解决什么问题、维护状态怎么样、适合本地还是公网、以及失败后的替代方案是什么。很多项目不是技术失败,而是方向失败。 + +### 软 CTA + +`这也是我为什么先做部署前检查清单。` + +## X / 短帖 1 + +`很多 GitHub 项目不是死在“不会开发”,而是死在“部署前没有把关键问题想明白”。本地能跑,不等于值得上线。` + +## X / 短帖 2 + +`部署前最该确认的,往往不是“怎么启动”,而是:值不值得部署、数据会去哪、哪些东西不能暴露到公网。` + +## X / 短帖 3 + +`如果你已经选好了一个开源 AI / Web 项目,但现在还在靠“先跑起来再说”推进,后面大概率会在配置、风险和改造优先级上付出更大代价。` + +## X / 短帖 4 + +`真正稳的第一步,不是立刻开干,而是先把部署前该确认的事梳理清楚。清单化,比盲试更快。` + +## X / 短帖 5 + +`一个项目“看起来很强”不等于“值得你真的部署”。方向错误时,部署越快,浪费越快。` + +## 配图建议 + +- 终端 + checklist 叠加画面 +- GitHub repo 页面 + 风险标注感视觉 +- “Local works / Production breaks” 对比图 +- 配置项、数据库、域名、锁图标等元素组合 + +## 推荐发布顺序 + +1. 短帖 1 +2. Shorts 角度 1 +3. 首发文章 +4. 短帖 4 +5. Shorts 角度 2 From 1e57d1f72d639232c00c6ae95e60a46aad9fb43f Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 31 Mar 2026 12:02:52 +0800 Subject: [PATCH 10/27] Draft launch and hardening SOP asset --- docs/Roadmap.md | 3 +- ...penSourceAIProjectLaunchAndHardeningSOP.md | 270 ++++++++++++++++++ docs/assets/README.md | 2 +- 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 docs/assets/OpenSourceAIProjectLaunchAndHardeningSOP.md diff --git a/docs/Roadmap.md b/docs/Roadmap.md index e19e3c9ee..5a0044b1d 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -94,7 +94,7 @@ This layer is allowed, but it should finance the earlier layers rather than domi ## Phase 5: Monetization Experiments - [ ] Define the first affiliate-safe topic cluster -- [ ] Define the first paid digital asset to test +- [x] Define the first paid digital asset to test - [ ] Define the first low-touch offer, only if needed as bootstrap revenue - [ ] Map which content types should lead to which monetization type @@ -146,5 +146,6 @@ If the answer to 1-3 is "no", it is probably off-strategy. - [x] Create one pilot downloadable asset draft - [x] Create one pilot article draft and one short-content pack that lead into it - [x] Design the second-stage paid SOP/template that the lead magnet should eventually feed into +- [x] Draft the first paid SOP body - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow diff --git a/docs/assets/OpenSourceAIProjectLaunchAndHardeningSOP.md b/docs/assets/OpenSourceAIProjectLaunchAndHardeningSOP.md new file mode 100644 index 000000000..833ff8033 --- /dev/null +++ b/docs/assets/OpenSourceAIProjectLaunchAndHardeningSOP.md @@ -0,0 +1,270 @@ +# 开源 AI 项目上线与基础加固 SOP(第一版) + +## 适用对象 + +- 已经完成第一轮项目筛选的人 +- 已经决定要部署某个开源 AI / Web 项目的人 +- 不想只停留在“本地能跑”,而是想把项目推进到“第一版可用”的人 +- 想先做一轮基础加固,而不是一上来就走到重度安全工程的人 + +## 这份 SOP 的边界 + +这不是一份“绝对安全上线手册”。 + +它更准确的定位是: + +> 帮你把一个开源 AI / Web 项目,从“准备开始部署”推进到“第一版可用、明显风险已收敛、后续可继续演进”的执行 SOP。 + +它关注的是: + +- 部署顺序 +- 决策优先级 +- 上线前必须确认的关键点 +- 基础风险收敛 + +它不承诺: + +- 一次做到企业级完备安全 +- 覆盖所有技术栈与所有极端场景 +- 替代架构设计与长期运维体系 + +## 推荐使用方式 + +更稳的顺序是: + +1. 先用《开源 AI 项目部署前检查清单》判断项目是否值得部署 +2. 再用这份 SOP 推进真正的第一版上线 +3. 上线后再根据实际使用情况进入第二轮改造或加固 + +## 阶段 0:先定义本次上线的目标 + +开始前先写一句话: + +> 这次上线的目标是什么? + +更好的答案通常是: + +- 先验证核心流程能跑通 +- 先让固定用户可用 +- 先跑一个稳定的第一版 + +不好的答案通常是: + +- 一次上线所有功能 +- 一次做成长期版本 +- 一次把架构、加固、扩展性都做到极致 + +### 输出物 + +- 一句话上线目标 +- 本次不做的范围 +- 成功标准(例如:能登录、能跑主流程、固定用户可访问) + +## 阶段 1:确认项目与环境是否匹配 + +### 要做的事 + +- 确认项目适合本地 / 内网 / 公网哪种场景 +- 确认依赖版本、运行环境、数据库、对象存储、反代等基础组件 +- 确认文档是否还可信 +- 确认这个项目不是已经停止维护太久 + +### 核心问题 + +- 这个项目到底是不是适合我现在的目标? +- 我的环境适配它,还是只是勉强能试? +- 如果它失败,我的替代方案是什么? + +### 通过标准 + +- 你能说清楚项目用途 +- 你知道需要哪些依赖 +- 你知道应该部署在哪里 + +## 阶段 2:梳理配置与环境变量 + +这是最容易把人拖进“明明都填了为什么还不对”的阶段。 + +### 要做的事 + +- 找出所有必填环境变量 +- 区分数据库、第三方 API、认证、存储、域名相关变量 +- 确认哪些值不能继续用默认占位 +- 把真实密钥和代码分离 + +### 最小原则 + +- 不把真实密钥写死在仓库里 +- 不把测试配置直接带到准备上线的环境 +- 不默认 `.env.example` 就等于生产可用配置 + +### 输出物 + +- 一份当前环境变量清单 +- 一份“必须先确定”的变量列表 + +## 阶段 3:建立测试环境并跑通核心流程 + +不要一开始就把项目推到最终生产环境。 + +### 要做的事 + +- 先准备最小测试环境 +- 跑通核心启动流程 +- 至少验证一遍最关键的主路径 + +### 核心原则 + +- 本地能跑,只代表“代码有机会活着” +- 测试环境能跑,才说明“上线开始有现实意义” + +### 要验证的最小主路径 + +根据项目不同,至少挑一个: + +- 登录 +- 创建 / 保存 +- 上传 / 下载 +- 触发 AI 请求 +- 后台管理主操作 + +## 阶段 4:确认数据落点与备份最小方案 + +很多人直到项目上线后,才第一次认真想“数据到底存哪”。 + +### 要做的事 + +- 确认数据是本地文件、数据库还是第三方平台 +- 确认哪些数据丢失会非常麻烦 +- 准备最小备份方案 +- 想一次回滚路径 + +### 最低要求 + +- 你知道重要数据在哪里 +- 你知道怎么备份一次 +- 你知道如果今天回滚,大概从哪开始 + +## 阶段 5:处理公网暴露前的基础风险 + +这一步是“基础加固”,不是“完整安全审计”。 + +### 必须优先看的内容 + +- 默认账号 / 默认密码 +- 未加鉴权的管理页面 +- 调试端点 +- 测试模式 +- 公开可见的敏感报错 +- 环境变量泄露风险 +- 日志是否会暴露内部结构 + +### 基础收敛动作 + +- 替换默认凭据 +- 关闭无必要调试入口 +- 不把管理后台默认暴露到公网 +- 给必要接口加上最基础的鉴权或访问限制 +- 检查日志和页面报错是否泄露路径、密钥、系统信息 + +### 这一步的目标 + +不是做到完美,而是先把“明显危险且很容易被踩中的点”先消掉。 + +## 阶段 6:补齐域名、HTTPS、反代与访问策略 + +如果项目要对外访问,这一步不能拖到最后。 + +### 要做的事 + +- 配域名 +- 配 HTTPS +- 明确反向代理层 +- 确认哪些路径公开,哪些路径限制访问 + +### 核心问题 + +- 这个项目是完全公开,还是只给少量固定用户? +- 某些端点是否应该只在内网或后台可见? +- 域名切换或服务器迁移时,最可能卡在哪? + +## 阶段 7:上线前最后一轮检查 + +这是“差不多”最容易骗自己的地方。 + +### 上线前至少确认 + +- 最关键流程已经真实走过一遍 +- 最可能坏掉的三个地方你已经知道 +- 挂了以后怎么恢复你心里有数 +- 当前版本的目标依然清楚,没有中途膨胀 + +### 不要做的事 + +- 不要在上线前最后一小时临时大改 +- 不要把新功能、UI 重构、权限改造一起塞进同一轮上线 +- 不要把“先发上去看看”当成正式策略 + +## 阶段 8:上线后的 24 小时观察 + +很多项目死在“刚上线那一下”,也死在“上线后没有人看”。 + +### 要做的事 + +- 看启动日志 +- 看运行日志 +- 看关键路径有没有持续成功 +- 看是否出现意外暴露、权限错误、存储异常 + +### 观察重点 + +- 登录是否正常 +- AI 请求是否稳定 +- 数据写入是否正常 +- 外部访问路径是否和预期一致 + +## 阶段 9:记录复盘,准备第二轮资产化 + +这一阶段非常关键,因为它决定你做的是一次性劳动,还是可复用资产。 + +### 上线后至少记录 + +- 这次最容易出错的 3 个点 +- 哪些判断事前做对了 +- 哪些步骤以后可以模板化 +- 哪些内容适合整理成文章、清单、SOP、模板 + +### 资产化方向 + +每做完一次上线或加固,都问: + +- 这能不能写成文章? +- 这能不能补进检查清单? +- 这能不能变成以后更完整的 SOP 模块? + +## 一份可直接照做的最小执行顺序 + +1. 明确本次上线目标 +2. 确认项目适配度 +3. 梳理环境变量 +4. 建测试环境并跑主流程 +5. 确认数据与备份 +6. 做一轮基础风险收敛 +7. 配好域名 / HTTPS / 反代 +8. 上线前做最后一轮检查 +9. 上线后观察 24 小时 +10. 立即复盘并沉淀为资产 + +## 最后 + +如果说免费清单解决的是: + +> “我开始之前该确认什么?” + +那么这份 SOP 解决的是: + +> “我已经决定要做了,应该按什么顺序推进,才能尽量少踩坑?” + +真正有效的上线,不是“我终于把它跑起来了”,而是: + +> 我知道为什么要这样部署、哪些风险已经先收敛了、哪些问题可以后面再处理,而且这次经验以后还能复用。 diff --git a/docs/assets/README.md b/docs/assets/README.md index e760e83c4..6ca7d9261 100644 --- a/docs/assets/README.md +++ b/docs/assets/README.md @@ -10,6 +10,6 @@ Current scope: - long-form article drafts - first-wave content topic clusters - short-form content packs -- future SOP / template drafts +- SOP / template drafts These files are intentionally written as working assets, not just abstract strategy notes. From 17bd832bd869068f19813ac590a4290608f0712d Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 31 Mar 2026 20:57:53 +0800 Subject: [PATCH 11/27] Document MoneyPrinter strategy and checklist funnel progress --- .gitignore | 1 + AGENTS.md | 22 ++ ...FzhangChecklistSiteImplementationPrompt.md | 148 ++++++++ docs/FzhangEmailAutomationBlueprint.md | 342 ++++++++++++++++++ docs/FzhangSiteAcceptanceAudit.md | 132 +++++++ docs/Roadmap.md | 61 +++- ...nSourceAIDeploymentChecklistLandingPage.md | 81 ++++- ...enSourceAIDeploymentChecklistPostSubmit.md | 75 +++- 8 files changed, 853 insertions(+), 9 deletions(-) create mode 100644 docs/FzhangChecklistSiteImplementationPrompt.md create mode 100644 docs/FzhangEmailAutomationBlueprint.md create mode 100644 docs/FzhangSiteAcceptanceAudit.md diff --git a/.gitignore b/.gitignore index 72a0a91df..a4dd817a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ __pycache__ config.json .mp/ +.playwright-mcp/ venv/ Songs/ google-maps-scraper-0.9.7/ diff --git a/AGENTS.md b/AGENTS.md index 1d438199f..ae076b013 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,27 @@ # Repository Guidelines +## Current Product Direction +- This fork is Frank's custom `MoneyPrinter`, not a generic client-acquisition helper. +- Prioritize business layers in this order: + - `Asset Printer`: reusable content assets, checklists, SOPs, templates, comparison pages. + - `Lead Printer`: owned audience, subscribers, repeat traffic, search/social entry points. + - `Cash Printer`: selective service revenue only as bootstrap support. +- Strategy test for new work: + - Prefer features and content that create reusable assets, strengthen owned audience, or improve low-touch monetization. + - Avoid changes that mainly optimize for selling more hours or turning the repo into a generic agency machine. +- Current first asset path: + - free asset first: `开源 AI 项目部署前检查清单` + - then paid asset: launch / hardening SOPs, templates, or other low-touch digital products +- Site positioning: + - `fzhang.dev` should remain content-first. + - Homepage CTA should bias toward owned-asset capture, not hard service selling. +- Canonical strategy docs: + - `docs/FrankMoneyPrinter.md` + - `docs/Roadmap.md` + - `docs/FirstAssetSpec.md` + - `docs/FinancialFreedomPath.md` + - `docs/FzhangHomepageCopy.md` + ## Project Structure & Module Organization - `src/` contains the application code. Use `src/main.py` as the interactive entrypoint. - `src/classes/` holds provider-specific components (for example `YouTube.py`, `Twitter.py`, `Tts.py`, `AFM.py`, `Outreach.py`). diff --git a/docs/FzhangChecklistSiteImplementationPrompt.md b/docs/FzhangChecklistSiteImplementationPrompt.md new file mode 100644 index 000000000..ce679601e --- /dev/null +++ b/docs/FzhangChecklistSiteImplementationPrompt.md @@ -0,0 +1,148 @@ +# 给另一个 AI 的站点改造提示词 + +你现在要修改 `fzhang.dev` 的站点源码。不要泛泛给建议,直接完成实现。 + +## 背景 + +- 站点是 Frank 的个人内容站,不是 generic agency site +- 当前免费资源页 URL: + - `/resources/open-source-ai-deployment-checklist/` +- 当前公开相关文章: + - `/posts/deploy-github-project-10-checks/` +- 当前订阅页: + - `/subscribe/` +- 当前资源页表单使用 `Formspree` +- 当前订阅页是 RSS-only + +## 这次改造的核心目标 + +1. 让“免费清单”页和公开文章拉开明确层级差异 +2. 让资源领取后能进入成熟的邮件后续更新流 +3. 保持站点内容气质,不把首页或资源页做成夸张销售页 + +## 必须实现的页面改动 + +### 资源页 `/resources/open-source-ai-deployment-checklist/` + +做以下改动: + +- 保留当前主题与整体风格 +- 在首屏下方、表单上方新增一个区块,标题建议: + - `这份资源和公开文章有什么区别` +- 这个区块要明确讲清楚: + - 公开文章是解释版 + - 免费清单是执行版 + - 公开文章帮助理解问题 + - 免费清单帮助真正部署前逐项核对 + +- 新增一个 `清单预览` 区块,但不要把整个资源全文公开 +- 预览里至少展示 4 到 6 个检查维度,例如: + - 部署场景判断 + - 环境变量梳理 + - 数据落点 + - 公网暴露风险 + - 回滚与恢复 + +- 表单降摩擦: + - `email` 保持必填 + - `name` 保持可选 + - `message` 改成折叠式可选,默认不要大面积暴露 + +- 表单附近必须新增许可说明文案: + - 我会把这份资源发给你 + - 后续如果有这条主题下的更新,也会优先发给你 + - 可以随时退订 + +- 当前页面底部已经有相关文章链接,但文案不够强 + - 改成更明确的对照式引导 + - 意图是: + - 想看解释版 -> 读文章 + - 想直接执行 -> 先领清单 + +### 订阅页 `/subscribe/` + +不要再只保留 RSS。 + +改成双入口结构: + +- 主入口:邮件订阅 +- 次入口:RSS 订阅 + +要求: + +- 邮件订阅在视觉上高于 RSS +- RSS 仍然保留,避免破坏站点气质 +- 订阅页文案要解释: + - 如果你想第一时间收到资源和专题更新,用邮件 + - 如果你只想安静地在阅读器里追踪,用 RSS + +## 必须实现的邮件流改造 + +不要把它做成“个人邮箱自动回复”。 + +改成成熟订阅方案: + +- 资源交付邮件 +- 后续自动序列 +- 后续 RSS / digest 更新 + +## 推荐技术方案 + +优先采用: + +- 前端表单 -> 你的 serverless endpoint +- Turnstile 继续保留 +- endpoint 发送资源交付邮件 +- endpoint 调用 `Buttondown` API 创建订阅者并打标签 +- `Buttondown` 负责 automations 与 RSS-to-email + +如果你暂时不想替换掉 `Formspree`,至少做到: + +- `Formspree` 继续接表单 +- 开启 autoresponse 发送资源 +- 再把提交同步到 `Buttondown` + +## 推荐标签 + +给这类订阅者至少打上: + +- `lead-magnet` +- `resource-checklist` +- `topic-deployment` +- `source-fzhang-dev` + +## 推荐邮件流 + +### Email 1 + +立即发送,交付资源。 + +### Email 2 + +延迟 2 天,告诉用户这份清单最适合什么时候打开,并引导去看相关文章。 + +### Email 3 + +延迟 5 到 7 天,承接到更完整的 SOP / 模板方向。 + +### Ongoing + +进入站点更新流,优先周更 digest,不要每篇文章即时轰炸。 + +## 文案约束 + +- 不要写成夸张营销话术 +- 不要让页面像卖课页 +- 不要让服务 CTA 压过资源领取 +- 不要模糊“公开文章”和“免费资源”的差异 +- 不要在第一屏就索取过多信息 + +## 交付要求 + +你最终需要输出: + +1. 修改后的页面代码 +2. 表单提交链路代码 +3. 邮件自动化接入说明 +4. 若用了环境变量,列出新增变量 +5. 若需要迁移已有 `Formspree` 逻辑,写清迁移步骤 diff --git a/docs/FzhangEmailAutomationBlueprint.md b/docs/FzhangEmailAutomationBlueprint.md new file mode 100644 index 000000000..4fb3d3a4b --- /dev/null +++ b/docs/FzhangEmailAutomationBlueprint.md @@ -0,0 +1,342 @@ +# fzhang.dev 免费资源领取与自动回信蓝图 + +## 当前实站状态 + +我已实际检查 `https://www.fzhang.dev/` 与 `https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/`,当前状态是: + +- 免费资源页存在,当前前端表单已提交到自建 `/api/subscribe` +- 当前资源页表单字段包括: + - `email` + - `name` + - `message` + - 隐藏字段 `request_type=free_resource_download` + - 隐藏字段 `signup_intent=resource-checklist` + - 隐藏字段 `resource=开源 AI 项目部署前检查清单` + - 隐藏字段 `topic=deployment` + - 隐藏字段 `source_page=/resources/open-source-ai-deployment-checklist/` + - 隐藏字段 `download=/downloads/open-source-ai-deployment-checklist.md` +- 当前 `订阅` 页已经不是 RSS-only,而是邮件订阅 + RSS 双入口 +- 当前成功页已经显示“先确认邮箱,再送达清单”的 double opt-in 式引导 + +这意味着: + +- 你已经有资源领取入口 +- 站点结构已经基本切换到成熟订阅路径 +- 但是否真的完成邮件送达、标签写入和自动序列,仍需要真实邮箱验收 + +## 当前验收结论 + +根据线上页面检查,下面这些已经基本成立: + +- 资源页已明确区分公开文章与执行版资源 +- 表单已切到自建接口而不是纯表单托管 +- 订阅页已完成邮件 + RSS 双路径 +- 成功页已具备确认订阅与后续 digest 预期管理 + +还不能只靠浏览器确认的部分: + +- 确认邮件是否真实发出 +- 资源交付邮件是否真实发出 +- 是否写入正确标签 +- 自动序列是否按时触发 +- 退订入口是否真实可用 + +所以当前状态更准确的说法是: + +> 前端与信息架构已经明显升级,但邮件闭环仍需要真实邮箱验收。 + +## 推荐方案 + +不要把“自动回信”理解成邮箱规则自动回复。 + +更成熟的做法是: + +`资源领取表单 -> 立即交付邮件 -> 进入订阅系统 -> 标签化 -> 自动序列 -> 周更或月更更新` + +我建议你采用两层结构: + +### 第一层:立即交付 + +负责把免费资源立刻发出去。 + +可选实现: + +- 继续使用 `Formspree` 自动回复 +- 或改成你自己的 serverless endpoint 发送事务型邮件 + +### 第二层:长期订阅 + +负责后续更新、标签、分组和自动序列。 + +我建议优先用 `Buttondown`,原因是它更贴近你的博客形态: + +- 支持标签与自动化 +- 支持 RSS-to-email +- 适合内容站而不是纯销售漏斗站 +- 支持自定义嵌入表单和 metadata + +## 为什么不建议只靠 Formspree + +`Formspree` 适合做表单接收和简单自动回复,但不适合作为长期订阅系统。 + +原因: + +- 它不是完整的 newsletter / subscriber system +- 后续更新、标签、自动序列、分群都不够自然 +- 你最终还是会需要一个专门的订阅平台 + +## 为什么更适合 Buttondown + +根据 Buttondown 官方文档,它支持: + +- 通过 API 创建 subscriber +- 通过标签做分群 +- 基于 subscriber confirmed 等触发器做 automations +- 基于 RSS 自动发送站点更新 + +这和你当前的站点结构是匹配的: + +- 你本来就有 RSS +- 你的网站本来就是内容站 +- 你后续需要的是“围绕主题的持续更新”,不是一次性表单通知 + +## 两种落地路径 + +### 路径 A:最快可用 + +保留当前 `Formspree` 表单。 + +实现方式: + +1. 开启 `Formspree` 自动回复,立即发送清单 +2. 如果你的 Formspree 计划支持 Webhooks,把提交同步到 `Buttondown` +3. 在 Buttondown 里创建标签、自动序列和 RSS-to-email + +优点: + +- 改动最小 +- 站点前端几乎不用大改 + +缺点: + +- 对 Formspree 计划有依赖 +- 数据链路拆成两段 + +### 路径 B:更干净的长期方案 + +把表单提交改到你自己的 serverless endpoint。 + +推荐部署位置: + +- Cloudflare Workers +- Vercel Functions + +服务分工: + +- Turnstile 继续做人机校验 +- 你的 endpoint 接收表单 +- endpoint 发送一封事务型资源交付邮件 +- endpoint 再把订阅者写入 Buttondown + +优点: + +- 你完全掌控数据和流程 +- 不依赖 Formspree 的 webhook 计划 +- 后续接更多资源、更多标签、更多序列更稳 + +缺点: + +- 需要一次真正的工程实现 + +## 我建议你选哪条 + +如果你想最快上线: + +- 先走 `路径 A` + +如果你准备认真把站点做成长期内容资产系统: + +- 直接走 `路径 B` + +我更推荐 `路径 B`,因为它更接近成熟订阅方案,也更符合你后续会继续扩资源、扩标签、扩自动化的方向。 + +## 推荐的数据模型 + +无论选哪条路径,至少统一这些字段: + +- `email` +- `name` +- `resource` +- `request_type` +- `source_page` +- `interest_topic` +- `submitted_at` + +推荐标签: + +- `lead-magnet` +- `resource-checklist` +- `topic-deployment` +- `source-fzhang-dev` + +如果后续还会有别的资源,再继续扩: + +- `resource-self-hosting-risk-sheet` +- `resource-ai-tool-stack` + +## 推荐的订阅逻辑 + +### 最成熟的处理方式 + +1. 用户提交表单 +2. 立即收到“资源交付邮件” +3. 同时进入“邮件订阅确认流程” +4. 只有确认后,才进入后续更新流 + +这比“提交后直接把人扔进长期群发”更成熟,原因是: + +- 更合规 +- 更少垃圾地址 +- 打开率更高 +- 长期列表质量更好 + +## 推荐的自动邮件结构 + +### Email 1:资源交付 + +触发: + +- 表单提交成功后立即发送 + +目的: + +- 把资源交付出去 +- 明确“解释版 vs 执行版”的差异 +- 给一个低摩擦下一步 + +核心内容: + +- 下载链接 +- 一句使用建议 +- 一篇相关文章入口 + +### Email 2:使用提醒 + +触发: + +- 订阅确认后 2 天 + +目的: + +- 提高资源实际打开率 +- 告诉读者什么时候应该打开这份清单 + +### Email 3:主题深化 + +触发: + +- 订阅确认后 5 到 7 天 + +目的: + +- 引到更完整的 SOP 方向 +- 观察真实需求反馈 + +### Email 4 之后:站点更新 + +触发: + +- 周更 digest 或按 RSS 生成的更新邮件 + +建议: + +- 不要每篇文章都即时轰炸 +- 优先周更 +- 后续如果能按 tag 发,只给部署相关订阅者发对应内容更好 + +## 你的站点应该怎么改 + +### 资源页 + +- 保留资源领取页 +- 明确说明“这不是公开文章复述” +- 增加执行预览 +- 降低表单摩擦 +- 增加许可说明: + - 会收到这份资源 + - 可能收到这一主题下的后续更新 + - 可随时退订 + +### 订阅页 + +现在的订阅页只有 RSS,这不够。 + +建议改成双入口: + +- 主要入口:邮件订阅 +- 次要入口:RSS 订阅 + +这样不会破坏你喜欢 RSS 的站点气质,同时也能承接资源用户。 + +## 实现步骤 + +### 方案 A:Formspree + Buttondown + +1. 在 Formspree 开启 autoresponse +2. 交付第一封资源邮件 +3. 若你的 Formspree 计划支持 Webhooks,则配置 webhook +4. webhook 把 `email/name/resource/source_page` 发到你的同步服务 +5. 同步服务调用 Buttondown API,创建 subscriber 并打标签 +6. 在 Buttondown 中创建: + - welcome / nurture automation + - RSS-to-email automation + +### 方案 B:Serverless + Buttondown + +1. 前端表单发到 `/api/resource-signup` +2. 后端验证 Turnstile +3. 后端发送资源交付邮件 +4. 后端调用 Buttondown API 创建 subscriber +5. subscriber 打上: + - `lead-magnet` + - `resource-checklist` + - `topic-deployment` + - `source-fzhang-dev` +6. Buttondown 负责后续 automation 和 RSS-to-email + +## 关键优化点 + +### 1. 不要把“后续更新”说得太虚 + +改成更具体的话术: + +- `后续如果我继续完善这条线,比如更完整的 SOP、风险速查表或相关文章更新,也会优先发给你。` + +### 2. 不要一上来收太多信息 + +资源领取阶段先拿: + +- 邮箱 +- 可选称呼 + +项目上下文可以在后续邮件里再收。 + +### 3. 不要把订阅页继续做成 RSS-only + +RSS 应该保留,但不该继续独占“订阅”入口。 + +### 4. 把资源交付和长期订阅分层 + +这是成熟方案最重要的区别之一。 + +- 资源交付邮件:事务型 +- 后续更新邮件:订阅型 + +## 官方文档依据 + +- Formspree autoresponse: https://help.formspree.io/hc/en-us/articles/360025007233-Sending-a-confirmation-or-response-email +- Formspree webhooks: https://help.formspree.io/hc/en-us/articles/360015234873-Webhooks +- Buttondown automations: https://docs.buttondown.com/automations-introduction +- Buttondown create subscriber API: https://docs.buttondown.com/api-subscribers-create +- Buttondown RSS-to-email: https://docs.buttondown.com/rss-to-email +- Buttondown subscriber base / embed form / metadata: https://docs.buttondown.com/building-your-subscriber-base diff --git a/docs/FzhangSiteAcceptanceAudit.md b/docs/FzhangSiteAcceptanceAudit.md new file mode 100644 index 000000000..cd4201508 --- /dev/null +++ b/docs/FzhangSiteAcceptanceAudit.md @@ -0,0 +1,132 @@ +# fzhang.dev 首轮验收记录 + +日期: + +- `2026-03-31` + +验收方式: + +- 实际访问线上站点 +- 检查资源页、订阅页、成功页 +- 检查前端表单字段与提交目标 +- 不做真实邮箱提交,因此不包含邮件送达层的最终验收 + +## 验收范围 + +- `https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/` +- `https://www.fzhang.dev/subscribe/` +- `https://www.fzhang.dev/checklist-sent/` + +## 通过项 + +### 1. 资源页已明显拉开“公开文章 vs 执行版资源”的差异 + +实站现在已经新增并明确展示: + +- `这份资源和公开文章有什么区别` +- 公开文章是解释版 +- 免费清单是执行版 +- `清单预览` 区块 + +这解决了此前最容易让人误会的点:用户不再容易把资源页理解成“把公开文章换了个表单”。 + +### 2. 资源页已经切到自建提交端点 + +前端表单不再提交到 `Formspree`,而是: + +- `POST /api/subscribe` + +并带有这些关键字段: + +- `request_type=free_resource_download` +- `signup_intent=resource-checklist` +- `resource=开源 AI 项目部署前检查清单` +- `topic=deployment` +- `source_page=/resources/open-source-ai-deployment-checklist/` +- `download=/downloads/open-source-ai-deployment-checklist.md` + +这说明链路已经从“单纯表单工具”升级为“可被业务语义识别的订阅入口”。 + +### 3. 订阅页已从 RSS-only 改成邮件 + RSS 双路径 + +当前 `/subscribe/` 已明确区分: + +- 邮件订阅 +- RSS 保留 + +而且邮件订阅优先级已高于 RSS,符合之前的改造目标。 + +### 4. 成功页已经切成确认订阅逻辑 + +当前成功页不是简单的“提交成功”,而是: + +- `请先确认邮箱,清单随后送达` + +并明确说明: + +- 首次订阅者先收确认邮件 +- 已有订阅者走后续流程 +- 后续以 digest / 周更节奏发送,而不是每次即时轰炸 + +这已经接近成熟订阅方案的结构。 + +## 风险与未完成项 + +### 1. 邮件送达链路仍未做真实邮箱验收 + +目前还不能从浏览器侧证明以下事项已经真实成立: + +- 是否确实发出了确认邮件 +- 是否确实发出了资源交付邮件 +- 是否确实进入了自动序列 +- 是否确实写入了正确标签 +- 是否每封邮件都带退订入口 + +这些必须用真实测试邮箱完整跑一遍才能算通过。 + +### 2. `message` 文本框仍然直接可见 + +虽然它仍是可选项,但当前资源页里它仍直接暴露在主表单中。 + +这不算严重问题,但会继续增加一点点领取摩擦。 + +更优做法: + +- 改成折叠式可选问题 +- 或移到提交成功页 / 后续邮件中再收集 + +### 3. Turnstile / 前端资源还有一些控制台噪音 + +验收时看到了这些现象: + +- Cloudflare Turnstile 相关 401 / preload / CSP fallback 噪音 +- `favicon.ico` 404 + +这些不一定影响主流程,但值得做一次前端清洁。 + +## 建议的最终验收动作 + +用一个全新测试邮箱,完整跑下面一遍: + +1. 在资源页提交邮箱 +2. 确认是否收到确认邮件 +3. 点击确认链接 +4. 确认是否收到资源交付邮件 +5. 确认下载链接是否可用 +6. 检查邮件里是否有: + - 退订入口 + - 品牌一致的发件人 + - 合理的文案节奏 +7. 2 天后检查第二封邮件是否按计划触发 +8. 5 到 7 天后检查第三封邮件是否按计划触发 +9. 在订阅系统后台检查是否已打上正确标签 + +## 当前结论 + +如果只看前端与站点结构: + +- 这次改造已经明显成功 + +如果看完整业务闭环: + +- 还差最后一步:真实邮箱验收 diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 5a0044b1d..3de55c7f4 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -6,6 +6,38 @@ This roadmap is now aligned to a different end state: The fork is no longer primarily optimized around "more client work". +## Progress Snapshot + +As of 2026-03-31, the first strategy pass is no longer just a discussion thread. + +The following decisions are now effectively locked unless a later strategy reset overrides them: + +- this fork is optimizing for `Asset Printer` first, `Lead Printer` second, and `Cash Printer` only as bootstrap support +- the first capture path is a free deployment checklist, not a hard service CTA +- `fzhang.dev` should remain content-first rather than turning into a generic agency homepage +- the first monetization bridge is: free asset -> owned audience -> paid SOP / template -> later affiliate or low-touch offers + +The following work is already represented in committed docs or repo changes: + +- strategy docs exist for the overall specialization, monetization path, and first asset choice +- the content profile system has been reframed around asset-led prompts instead of only service-led positioning +- the first asset funnel has draft assets: + - free checklist + - download page copy + - post-submit copy + - first article draft + - first short-content pack + - first 10 long-tail topics + - first paid SOP draft +- homepage direction and CTA hierarchy are drafted, but site implementation is still pending + +Current gap summary: + +- measurement is not wired yet +- topic scoring is not implemented yet +- affiliate-safe comparison / recommendation clusters are not defined yet +- email delivery, tagging, and sequence timing still need true inbox verification + ## North Star The system should gradually make it easier to produce: @@ -71,8 +103,8 @@ This layer is allowed, but it should finance the earlier layers rather than domi - [x] Replace broad service-led prompts with monetizable-intent prompts - [ ] Create content variants for: -- [ ] deployment intent -- [ ] risk / hardening intent +- [x] deployment intent +- [x] risk / hardening intent - [ ] tool comparison intent - [ ] cost / trade-off intent - [ ] affiliate-safe recommendation intent @@ -89,8 +121,15 @@ This layer is allowed, but it should finance the earlier layers rather than domi - [x] Define one primary capture target: checklist download first - [ ] Add CTA variants that point to owned capture instead of direct call booking +- [ ] Turn resource capture into a mature email path instead of one-off form replies - [ ] Add measurement for capture conversion by topic type +Implementation note: + +- live site now uses a custom `/api/subscribe` endpoint for the checklist flow +- success page already frames the flow as confirmation-first, then resource delivery +- still needs real inbox verification before this phase item can be closed + ## Phase 5: Monetization Experiments - [ ] Define the first affiliate-safe topic cluster @@ -100,11 +139,19 @@ This layer is allowed, but it should finance the earlier layers rather than domi ## Phase 6: Site Integration -- [ ] Keep `fzhang.dev` primarily as a content site +- [x] Keep `fzhang.dev` primarily as a content site - [ ] Add a lightweight conversion path from homepage to owned assets +- [x] Make resource pages clearly stronger than adjacent public articles +- [x] Replace RSS-only subscription positioning with email + RSS dual paths - [ ] Add dedicated pages for resources, comparisons, or templates - [ ] Avoid turning the whole site into a generic service homepage +Direction note: + +- content-first site positioning is agreed and documented +- homepage conversion copy is drafted +- actual site implementation is still pending + ## Phase 7: Measurement - [ ] Track which topics produce: @@ -142,10 +189,16 @@ If the answer to 1-3 is "no", it is probably off-strategy. - [x] Rewrite the current account profile system around asset destination, not only service offer - [x] Draft the first 10 topic angles with monetizable intent - [x] Define the first lead magnet -- [ ] Define one homepage conversion block for `fzhang.dev` that points to an owned asset +- [x] Define one homepage conversion block for `fzhang.dev` that points to an owned asset - [x] Create one pilot downloadable asset draft - [x] Create one pilot article draft and one short-content pack that lead into it - [x] Design the second-stage paid SOP/template that the lead magnet should eventually feed into - [x] Draft the first paid SOP body - [x] Update `origin` / `upstream` remotes so this fork can be pushed cleanly - [x] Add a dedicated upstream sync script for the fork workflow + +## Executable Shortlist + +1. Upgrade the checklist landing page so visitors immediately understand it is an execution asset, not a gated copy of a public article. +2. Ship the first real email capture system: immediate resource delivery, confirmed follow-up sequence, and ongoing site updates. +3. Add first-pass measurement for the checklist funnel: page views, submits, confirmed subscribers, and downstream clicks. diff --git a/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md b/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md index 7fc12fb28..c65a93741 100644 --- a/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md +++ b/docs/assets/OpenSourceAIDeploymentChecklistLandingPage.md @@ -2,7 +2,13 @@ ## 页面目标 -让读者留下联系方式或完成订阅,领取第一份免费资源。 +让读者留下联系方式,领取第一份免费资源。 + +更重要的目标: + +- 明确告诉访客,这不是“把公开文章换个表单” +- 让访客一眼看懂:公开文章负责解释,免费清单负责执行 +- 在不损伤站点内容气质的前提下,提高资源领取转化率 ## 页面标题 @@ -16,7 +22,24 @@ `很多项目不是死在“不会开发”,而是死在“部署前没有把关键问题想明白”。` -`这份清单适合独立开发者、小团队和个人创业者。它不会教你空泛的“AI 创业建议”,而是帮你在真正动手之前,先把部署、配置、风险和后续维护中最关键的问题梳理清楚。` +`这份清单适合独立开发者、小团队和个人创业者。它不会重复一篇泛泛的概念文章,而是把部署前最该确认的事项压缩成一份可直接照着走的执行版检查表。` + +## 这份资源和公开文章有什么区别 + +### 建议放在首屏下方,表单上方 + +`如果你已经读过站里的相关文章,这里最需要讲清楚的一件事是:` + +- `公开文章` 更适合先理解问题、建立判断框架 +- `免费清单` 更适合真正准备部署时,按顺序逐项核对 +- `公开文章` 是解释版 +- `免费清单` 是执行版 +- `公开文章` 读完就结束 +- `免费清单` 可以在每次准备部署新项目时反复回看 + +### 建议用一句更短的总结 + +`如果公开文章回答的是“为什么很多项目会在部署前出问题”,这份清单回答的是“那我现在到底该先检查什么”。` ## 你会拿到什么 @@ -25,6 +48,22 @@ - `从项目是否值得部署,到配置、数据、鉴权、上线前确认的完整结构` - `适合后续继续延伸成自己的 SOP 或项目准备流程` +## 建议增加一个“清单预览”区块 + +不要把全部内容提前公开,但要给到足够具体的预览,降低“留邮箱却不知道拿到什么”的不确定感。 + +### 区块标题 + +`清单里会先带你检查什么` + +### 预览条目示例 + +- `这个项目到底适合本地、内网还是公网` +- `哪些环境变量必须先确定,哪些只是可选` +- `数据会落在哪里,出了问题怎么回滚` +- `哪些页面和端点绝对不该直接暴露到公网` +- `这次上线的目标到底是不是被你自己说清楚了` + ## 这份清单适合谁 - `已经选好了 GitHub 项目,但担心一上手就踩坑的人` @@ -46,10 +85,32 @@ ## 表单前引导 -`留下邮箱或订阅方式后,我会把这份清单发给你。` +`留下邮箱后,我会把这份清单直接发给你。` `后续如果我把这份清单扩展成更完整的《开源 AI 项目上线与基础加固 SOP》,你也会优先知道。` +`只会发送这份资源和与这条主题直接相关的后续更新,不会把你拉进泛泛的群发邮件。` + +## 表单策略建议 + +当前实站表单包含: + +- `email` +- `name`(可选) +- `message`(可选) + +建议改成更成熟的资源领取表单逻辑: + +- 邮箱保留必填 +- 称呼保留可选 +- “你现在在部署什么” 改成折叠式可选问题,或者提交成功页再问 + +原因: + +- 对 lead magnet 而言,首要目标是降低领取阻力 +- 可选文本框会让一部分本来愿意领取的人停下来 +- 成熟订阅方案通常先完成领取,再在后续邮件里渐进收集上下文 + ## CTA - 主按钮:`领取免费清单` @@ -60,6 +121,8 @@ `如果你后续对“如何从清单走到真正上线”更感兴趣,后续会有更完整的 SOP / 模板版本。` +`如果几分钟内没收到,请检查垃圾邮件;后续每封邮件都应带有清晰的退订入口和偏好管理说明。` + ## 页面下方补充文案 ### 为什么先做免费清单,而不是直接卖课或卖服务 @@ -68,6 +131,18 @@ `这份清单的意义,不是替你做决定,而是帮你在真正投入时间和成本之前,先把该确认的问题看清楚。` +## 页面底部的文章链接建议改写 + +当前页面已经链接到公开文章,但还不够强调两者差异。 + +建议把引导文案改成: + +`如果你想先看“解释版”,可以继续读这篇公开文章;如果你更想直接进入“执行版”,先把清单领走。` + +相关文章建议链接: + +- `部署一个 GitHub 项目前,最应该先确认的 10 件事` + ### 后续可能扩展的内容 - `开源 AI 项目上线与基础加固 SOP` diff --git a/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md b/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md index 17c932797..0a322d1d5 100644 --- a/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md +++ b/docs/assets/OpenSourceAIDeploymentChecklistPostSubmit.md @@ -4,14 +4,16 @@ ### 标题 -`清单已经准备好了` +`清单已经在路上` ### 正文 -`这份《开源 AI 项目部署前检查清单》会发送到你留下的联系方式。` +`这份《开源 AI 项目部署前检查清单》会发送到你留下的邮箱。` `如果你现在正处在“已经选好了项目,但还不确定应该怎么开始部署”的阶段,建议你先完整过一遍这份清单,再决定哪些问题必须现在处理,哪些可以后面再说。` +`后续如果你愿意,也会继续收到这一主题下的更新。每封邮件都应该能直接退订,不需要回复我手动处理。` + ### 按钮 - `返回首页` @@ -49,10 +51,79 @@ 如果你更想看系统化、一步步可执行的版本,后续更新会优先发给你。 +你之后收到的内容应该尽量保持克制,只围绕这条主题: + +- 资源更新 +- 相关新文章 +- 更完整的 SOP / 模板进展 + +不应该突然变成泛泛而谈的“AI 热点群发”。 + 附: - 免费清单:`(放下载链接或附件)` - 相关文章:`部署一个 GitHub 项目前,最应该先确认的 10 件事` +## 推荐的自动邮件序列 + +目标不是“多发”,而是建立成熟的资源领取后续流。 + +### Email 1: 立即发送 + +目的: + +- 交付资源 +- 解释资源和公开文章的区别 +- 给一个低压力的下一步 + +建议主题: + +- `你领取的部署前检查清单到了` +- `先把这份部署前检查清单收好` + +核心 CTA: + +- `下载清单` + +### Email 2: 延迟 2 天 + +目的: + +- 教对方怎么使用这份清单 +- 引导阅读最相关的公开文章 + +建议主题: + +- `这份清单最适合什么时候打开` +- `先别急着部署,先把这 10 件事过一遍` + +核心 CTA: + +- `去读相关文章` + +### Email 3: 延迟 5 到 7 天 + +目的: + +- 进一步建立“解释版 -> 执行版 -> SOP”的递进感 +- 测试对更完整产品的兴趣 + +建议主题: + +- `如果你已经开始部署,下一步可能需要这个` +- `清单之后,我准备继续整理什么` + +核心 CTA: + +- `回复我你最卡的环节` 或 `加入后续更新` + +### Ongoing: 后续更新 + +建议逻辑: + +- 已确认订阅的人进入站点更新流 +- 优先发送周更 digest,而不是每发一篇就轰炸一次 +- 如果后续有专题标签,优先只给“部署 / 自托管 / AI 项目上线”相关的人发对应更新 + ## Thank You 区块文案 如果页面支持提交成功后的内嵌推荐区块,可以加这段: From bb614254164797da6387fd0625241df0bf4261d4 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 31 Mar 2026 21:49:22 +0800 Subject: [PATCH 12/27] Document financial freedom execution stack --- docs/FinancialFreedomExecutionStack.md | 333 +++++++++++++++++++++++++ docs/Roadmap.md | 15 ++ 2 files changed, 348 insertions(+) create mode 100644 docs/FinancialFreedomExecutionStack.md diff --git a/docs/FinancialFreedomExecutionStack.md b/docs/FinancialFreedomExecutionStack.md new file mode 100644 index 000000000..5f5fb3b18 --- /dev/null +++ b/docs/FinancialFreedomExecutionStack.md @@ -0,0 +1,333 @@ +# Financial Freedom Execution Stack + +This document freezes the current cross-project conclusion into one operating model. + +It is intentionally practical. +It does not describe every possible future business. +It describes the current best interpretation of what Frank should optimize for next. + +## Core Thesis + +Financial freedom should not be treated as: + +- one breakthrough project +- one lucky viral cycle +- one immediate product bet + +It should be treated as a stacked system: + +1. cash flow that keeps the system alive +2. assets that compound over time +3. products that emerge from repeated proof + +## The Stack + +### Layer 1: Cash Flow + +Current role: + +- AI-assisted freelance delivery +- selective productized implementation +- narrowly scoped paid help where proof already exists + +Why it stays: + +- funds runway +- funds experimentation +- creates fresh real-world problems to document + +Rule: + +- cash flow is necessary +- but it is not the end state + +### Layer 2: Asset Compounding + +Current role: + +- long-tail articles on `fzhang.dev` +- free technical resources +- email capture +- SOP drafts +- templates +- reusable comparison and recommendation pages later + +This is the current highest-leverage layer. + +Why: + +- fits Frank's writing style and documentation habits +- does not require shallow daily performance content +- turns real delivery experience into repeatable value +- creates future audience and monetization leverage + +### Layer 3: Product Optionality + +Current role: + +- only build software products after repeated demand is visible +- use actual traffic, replies, downloads, and purchases as filters + +This means: + +- do not force a software product too early +- do not assume an ambitious idea is automatically the right first product +- let repeated proof narrow the product surface + +## Project Roles + +### `MoneyPrinterV2` + +Primary role: + +- the asset printing system + +It should help turn one proven idea into: + +1. article +2. short-form derivative +3. resource capture point +4. paid SOP or template path +5. later affiliate or low-touch monetization path + +This is the current main execution repo for the financial-freedom path. + +### `fzhang.dev` + +Primary role: + +- the trust surface +- the long-tail traffic surface +- the owned-audience capture surface + +It should stay content-first. + +It should not become a generic agency homepage. + +Its job is to: + +- attract the right readers +- convert some readers into subscribers or downloaders +- support later monetization pages + +### Knowledge Base + +Primary role: + +- source material +- decision filter +- evidence ledger + +The knowledge base should not only store ideas. + +It should feed: + +- article topics +- downloadable assets +- product filters +- postmortems +- proof of what actually worked + +Any idea that does not enter an execution path should remain dormant. + +### `social-auto-upload` + +Primary role: + +- distribution multiplier + +It is useful because it can reduce the friction of reposting content to more platforms. + +But it is not the core business. + +It amplifies assets that already deserve to exist. + +### `paperclip` + +Primary role: + +- later-stage product optionality + +Current judgment: + +- strategically interesting +- potentially high-upside +- not the best near-term primary monetization engine + +Why: + +- it is closer to a real product company bet +- it needs more maturity and clearer distribution for immediate monetization +- it should not displace the current asset-first path + +Rule: + +- treat `paperclip` as a later product lane, not the main short-term cash engine + +## Future `paperclip` Integration + +`paperclip` should only move from "interesting later product lane" to "active integration lane" when at least some of the following are true: + +- the content and resource system is already producing recurring proof +- the first paid SOP / template has real buyers +- repeated audience or customer signals point toward multi-agent coordination, operator workflows, or autonomous-company operations +- Frank has enough runway that a product bet will not choke the asset system + +Before that point, `paperclip` should mainly be treated as: + +- a strategic optionality repo +- a future case-study source +- a possible later software business + +Not as: + +- the current primary monetization engine +- the current main use of limited execution time + +### Practical Integration Path + +If `paperclip` becomes active later, the recommended order is: + +1. use `fzhang.dev` content to attract the right operator / builder audience +2. use `MoneyPrinterV2` to print topic clusters, guides, and assets around agent-company workflows +3. test small paid assets or research-driven offers around those workflows +4. only then decide whether `paperclip` itself should become a direct product lane + +### Constraint + +Do not let `paperclip` consume the execution budget that is currently needed to: + +- close the checklist funnel +- ship monetizable long-tail content +- validate paid SOP demand +- establish a topic ledger with real downstream value + +## Current Best Monetization Order + +The current recommended order is: + +1. free execution asset +2. owned audience capture +3. paid SOP / template +4. affiliate-safe comparison or recommendation assets +5. low-touch productized help only if useful as bootstrap revenue +6. larger software product only after strong repeated proof + +This order should come before: + +- broad service expansion +- pure affiliate-first behavior +- building a major software product too early + +## What Counts As Proof + +Do not promote an idea to the next layer without evidence. + +Useful proof includes: + +- page views from the right topic +- email signups +- resource downloads +- replies requesting deeper help +- paid purchases of a small asset +- repeated demand for the same implementation or question + +Weak proof includes: + +- vague compliments +- vanity impressions +- personal excitement without user response + +## 90-Day Operating Priorities + +### Priority 1: Close the checklist funnel + +This means: + +- true email delivery verification +- tagging and sequence verification +- resource delivery verification +- basic measurement + +### Priority 2: Publish monetizable long-tail content + +Focus topics: + +- deployment +- launch readiness +- hardening +- self-hosting trade-offs +- what breaks after setup + +Avoid: + +- generic AI hot takes +- broad commentary +- content with no capture or monetization path + +### Priority 3: Launch the first paid asset + +Primary candidate: + +- launch / hardening SOP + +Goal: + +- test low-touch revenue before larger product bets + +### Priority 4: Keep a narrow bootstrap service available + +Only if needed. + +Strong examples: + +- deployment review +- launch-readiness check +- basic hardening review + +Weak examples: + +- generic custom development offers +- broad "I can build anything" messaging + +## Resource Allocation + +Default current allocation: + +- `60%` cash flow and survival work +- `30%` asset compounding +- `10%` product optionality + +This should change only after assets begin to show real downstream value. + +## Topic Ledger Requirement + +Maintain a topic ledger for every serious topic cluster. + +Track at least: + +- topic +- article shipped +- short-form derivative shipped +- resource CTA used +- subscribers +- downloads +- replies +- product interest +- paid revenue if any + +Without this, it is too easy to confuse activity with progress. + +## Decision Filters + +Before starting new work, ask: + +1. Does this improve cash flow now? +2. Does this create or strengthen a reusable asset? +3. Does this convert rented reach into owned audience? +4. Does this create evidence for a future paid asset or product? +5. If it fails all of the above, why is it active now? + +## Current One-Sentence Strategy + +Use freelance cash flow to fund an asset-printing system, use the asset-printing system to build owned audience and paid SOPs, and let later software products emerge from repeated proof instead of premature ambition. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 3de55c7f4..29e82d352 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -30,6 +30,7 @@ The following work is already represented in committed docs or repo changes: - first 10 long-tail topics - first paid SOP draft - homepage direction and CTA hierarchy are drafted, but site implementation is still pending +- a cross-project execution summary now exists in `docs/FinancialFreedomExecutionStack.md` Current gap summary: @@ -202,3 +203,17 @@ If the answer to 1-3 is "no", it is probably off-strategy. 1. Upgrade the checklist landing page so visitors immediately understand it is an execution asset, not a gated copy of a public article. 2. Ship the first real email capture system: immediate resource delivery, confirmed follow-up sequence, and ongoing site updates. 3. Add first-pass measurement for the checklist funnel: page views, submits, confirmed subscribers, and downstream clicks. + +## Portfolio Rule + +This fork is not the entire financial-freedom system by itself. + +It is the current main execution repo inside a broader stack: + +- `MoneyPrinterV2` = asset printer +- `fzhang.dev` = trust + long-tail traffic + owned capture +- knowledge base = source material + evidence ledger + decision filters +- `social-auto-upload` = distribution multiplier +- `paperclip` = later-stage product optionality, not the current short-term cash engine + +If future work starts to blur these roles, use `docs/FinancialFreedomExecutionStack.md` as the reset point. From 0b6441c93c6566876aef78c0d9bdb1efcd01b857 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 31 Mar 2026 22:54:04 +0800 Subject: [PATCH 13/27] =?UTF-8?q?Chore=20=E6=B7=BB=E5=8A=A0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=BA=A7AGENTS.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index ae076b013..db660cca8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,30 @@ - `docs/FinancialFreedomPath.md` - `docs/FzhangHomepageCopy.md` +## Cross-Project Financial Freedom Context +- This repo should be evaluated as one lane inside Frank's broader financial-freedom system, not in isolation. +- Canonical cross-project references for that system: + - `docs/FinancialFreedomExecutionStack.md` + - `docs/Roadmap.md` + - `/Users/frank_zhang/Documents/文稿 - Frank's MacBook Air/Github项目/paperclip/doc/plans/2026-03-31-paperclip-financial-freedom-positioning.md` + - `/Users/frank_zhang/Library/Mobile Documents/com~apple~CloudDocs/Obsidian 库/5.知识库/07个人成长/08财务自由之路/1当前财务自由系统的项目分工与顺序(2026-03-31).md` +- When work touches monetization order, project prioritization, `fzhang.dev`, asset funnels, paid SOPs/templates, bootstrap services, or possible `paperclip` integration, consult the references above before making strategic changes. +- Current cross-project operating model: + - `cash flow survival layer + asset compounding layer + product optionality layer` + - `MoneyPrinterV2` is the current main execution repo for the asset-compounding layer. + - `fzhang.dev` is the trust, traffic, and owned-audience surface. + - The knowledge base is a source-material and evidence ledger, not just storage. + - `paperclip` is currently later-stage product optionality, not the main short-term monetization engine. +- Guardrail: + - Do not let `paperclip` or other product bets consume execution budget needed for the current asset loop: + - close the checklist funnel + - verify email delivery and tagging + - publish monetizable long-tail content + - validate paid SOP / template demand + - build proof from real traffic, downloads, replies, and purchases +- Promotion rule: + - Larger product bets should be activated by repeated external proof, not by excitement alone. + ## Project Structure & Module Organization - `src/` contains the application code. Use `src/main.py` as the interactive entrypoint. - `src/classes/` holds provider-specific components (for example `YouTube.py`, `Twitter.py`, `Tts.py`, `AFM.py`, `Outreach.py`). From 94e5ba6460aaeca97b685dbaf31c9c0f4143aa64 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:53:26 +0800 Subject: [PATCH 14/27] Document Buttondown prompts and content batch plan --- ...zhangButtondownFollowupAutomationPrompt.md | 150 ++++++++++++++++ .../FzhangButtondownUnsubscribeAuditPrompt.md | 111 ++++++++++++ docs/Roadmap.md | 10 ++ docs/assets/FirstContentBatchExecutionPlan.md | 168 ++++++++++++++++++ docs/assets/PaidSOPPathSpec.md | 161 +++++++++++++++++ docs/assets/README.md | 2 + 6 files changed, 602 insertions(+) create mode 100644 docs/FzhangButtondownFollowupAutomationPrompt.md create mode 100644 docs/FzhangButtondownUnsubscribeAuditPrompt.md create mode 100644 docs/assets/FirstContentBatchExecutionPlan.md create mode 100644 docs/assets/PaidSOPPathSpec.md diff --git a/docs/FzhangButtondownFollowupAutomationPrompt.md b/docs/FzhangButtondownFollowupAutomationPrompt.md new file mode 100644 index 000000000..40c8ed1b6 --- /dev/null +++ b/docs/FzhangButtondownFollowupAutomationPrompt.md @@ -0,0 +1,150 @@ +# 给另一个 AI 的 Buttondown 后续更新自动化提示词 + +你现在要审查并改进 `fzhang.dev` 当前“资源领取后,后续优先发相关文章和主题更新”的实现方式。 + +目标不是堆更多手工邮件,而是确认: + +1. 这件事在 Buttondown 里应该怎么自动化 +2. 如何保证不会给 Frank 增加过多运营负担 +3. 如何让“后续优先发送”真正可执行 + +## 当前业务目标 + +用户通过个人网站提交邮箱领取: + +- `开源 AI 项目部署前检查清单` + +之后希望实现: + +- 先发资源交付邮件 +- 再发少量后续邮件 +- 后续如果这条主题下扩展出新文章、资源、SOP,也能优先发给这批人 + +但前提是: + +- 不能让 Frank 进入高频手工运营 +- 不能每发一篇内容就手工给这批人发一封 +- 不能把整个系统做成很重的 CRM + +## 你必须先核对的 Buttondown 官方能力 + +请检查并利用这些能力: + +- Automations 支持: + - welcome sequences + - based on triggers / filters / actions +- Tags 支持: + - 通过 API 或订阅表单打标签 +- RSS-to-email 支持: + - 每篇更新自动发 + - 每周汇总发 + - 每月汇总发 +- Create subscriber API 默认 double opt-in + +## 当前判断方向 + +请围绕下面这个判断做验证或修正: + +### 最可能的低负担实现 + +资源领取用户进入一条单独的订阅路径: + +1. 提交资源表单 +2. double opt-in 确认 +3. 立即收到资源交付邮件 +4. 再进入一个短 welcome / nurture sequence +5. 后续通过 RSS-to-email 或定期 digest 自动接收相关更新 + +这比: + +- 每次手工群发 +- 每有新文章就手动筛人发 +- 靠个人邮箱规则自动回复 + +更合理。 + +## 你的任务 + +### 任务 1:判断“后续优先发给我”最适合落在哪条链路 + +请在下面几种方式里做选择并说明理由: + +- Buttondown welcome email + automations +- Buttondown automations + tags +- Buttondown RSS-to-email weekly digest +- 手工 newsletter segmentation +- 混合方案 + +### 任务 2:给出最推荐的低负担方案 + +必须明确: + +- 哪些内容应该自动发 +- 哪些内容不该自动发 +- 周更、月更、逐篇发,哪个更适合当前阶段 + +我更偏向的目标是: + +- 资源领取后 2 到 3 封自动后续邮件 +- 之后进入主题相关的 digest 更新 +- 不做高频手工运营 + +### 任务 3:设计标签与过滤逻辑 + +请基于当前资源页,给出建议标签,例如: + +- `lead-magnet` +- `resource-checklist` +- `topic-deployment` +- `source-fzhang-dev` + +并回答: + +- 后续新文章应该如何进入这条线 +- 是靠 tags 发,还是靠独立 automation,还是靠 RSS cadence + +### 任务 4:回答“会不会增加太多负担” + +请明确判断: + +- 当前最省力的实现是什么 +- 哪种实现会明显增加 Frank 的长期负担 +- 应该避免哪些“看起来先进、实际很重”的自动化设计 + +### 任务 5:给出建议的最终架构 + +输出一个简洁的自动化架构图或步骤: + +例如: + +`资源页 -> API -> Buttondown subscriber + tags -> confirmation -> welcome/resource email -> 2-step follow-up -> weekly RSS digest` + +## 输出要求 + +请按下面结构输出: + +1. 最推荐方案 +2. 为什么它负担最低 +3. 标签与分群设计 +4. 后续更新该如何自动发 +5. 不推荐的重方案 +6. 最终落地步骤 + +## 官方文档入口 + +- Automations: + - https://docs.buttondown.com/automations-introduction +- Welcome sequence: + - https://docs.buttondown.com/welcome-sequence +- RSS-to-email: + - https://docs.buttondown.com/rss-to-email +- Create subscriber API: + - https://docs.buttondown.com/api-subscribers-create +- Sending emails / unsubscribe: + - https://docs.buttondown.com/sending-emails#avoiding-the-promotions-tab + +## 额外要求 + +- 不要默认推荐复杂 CRM +- 不要把“后续优先发给我”设计成必须人工一封一封维护 +- 优先给出“当前阶段够用、未来可扩展”的方案 diff --git a/docs/FzhangButtondownUnsubscribeAuditPrompt.md b/docs/FzhangButtondownUnsubscribeAuditPrompt.md new file mode 100644 index 000000000..07d2dbd85 --- /dev/null +++ b/docs/FzhangButtondownUnsubscribeAuditPrompt.md @@ -0,0 +1,111 @@ +# 给另一个 AI 的 Buttondown 退订与合规检查提示词 + +你现在要审查并改进 `fzhang.dev` 当前的 Buttondown 邮件链路,重点是: + +1. 为什么确认邮件和资源交付邮件里看不到退订链接 +2. 哪些邮件必须有退订或订阅管理入口 +3. 应该如何用 Buttondown 的正确方式修复 + +不要泛泛给建议。请基于当前实现,给出明确判断、配置修改建议、模板修改方案和验证步骤。 + +## 当前已知情况 + +- 资源页和订阅页都已切到自建 `/api/subscribe` +- 新订阅者会收到确认邮件 +- 确认后会收到资源交付邮件 +- Buttondown 后台可以看到订阅者信息变化 +- 但用户现在看不到明确的退订链接 + +## 你必须先核对的 Buttondown 官方约束 + +请先对照这些事实检查现有实现是否合理: + +- Buttondown 官方文档显示: + - `confirmation email` 可用变量只有 `confirmation_url`、`newsletter.name`、`newsletter.description`、`newsletter.absolute_url`、`subscriber.email` + - 也就是说,确认邮件模板本身没有 `unsubscribe_url` +- Buttondown 官方文档显示: + - 普通邮件可以手动插入 `{{ unsubscribe_url }}` + - Buttondown 也会在邮件 footer 自动附加退订链接 +- Buttondown 官方文档显示: + - `welcome email` 支持 `unsubscribe_url` + - `welcome email` 支持 `manage_subscription_url` +- Buttondown 官方文档显示: + - 开启 Portal 后,订阅者可通过 `manage_subscription_url` 管理订阅 + - Portal 也会自动出现在邮件 footer + +## 你的任务 + +### 任务 1:判断当前“看不到退订链接”是不是配置问题,还是 Buttondown 机制本来如此 + +你要明确区分: + +- 确认邮件为什么可能天然没有退订链接 +- 资源交付邮件为什么理论上应该有退订或管理入口 + +### 任务 2:检查当前站点链路里,资源交付邮件到底属于哪一类 + +判断它是: + +- Buttondown welcome email +- Buttondown automation email +- 普通 newsletter email +- 还是自定义事务型邮件 + +并分别说明: + +- 如果它是 welcome email,应该怎么写模板 +- 如果它是 automation / newsletter email,应该怎么保证 footer 和 `unsubscribe_url` +- 如果它是自定义事务型邮件,应该如何补订阅管理入口 + +### 任务 3:给出最推荐的修复方案 + +你必须给出一个明确优先级,不要只罗列可能性。 + +至少包含: + +1. 是否开启 Buttondown Portal +2. 是否在 welcome / resource delivery 邮件正文里显式加入: + - `{{ unsubscribe_url }}` + - `{{ manage_subscription_url }}` +3. 确认邮件里如果不能提供退订链接,应该用什么替代文案降低困惑 +4. 哪些邮件必须出现退订或管理订阅入口 + +### 任务 4:给出验证 checklist + +至少覆盖: + +- 新邮箱首次订阅 +- 收到确认邮件 +- 确认后收到资源交付邮件 +- 邮件正文是否有订阅管理入口 +- footer 是否自动出现 +- 点击后能否进入管理 / 退订页面 +- 旧订阅者再次领取资源时是否仍能看到订阅管理入口 + +## 输出要求 + +请按下面结构输出: + +1. 当前问题的根因判断 +2. Buttondown 机制边界 +3. 推荐修复方案 +4. 需要修改的模板文案 +5. 需要检查的 Buttondown 后台设置 +6. 一份逐项验收 checklist + +## 官方文档入口 + +- Confirmation email: + - https://docs.buttondown.com/transactional-emails-confirmation +- Welcome email: + - https://docs.buttondown.com/transactional-emails-welcome +- Sending emails / custom unsubscribe links: + - https://docs.buttondown.com/sending-emails#avoiding-the-promotions-tab +- Portal: + - https://docs.buttondown.com/portal + +## 额外要求 + +- 不要建议“手动回复用户完成退订” +- 不要把“没有退订链接”简单归因于前端问题 +- 要明确区分确认邮件、欢迎邮件、资源交付邮件、普通更新邮件的责任边界 diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 29e82d352..94a6a63ac 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -30,6 +30,7 @@ The following work is already represented in committed docs or repo changes: - first 10 long-tail topics - first paid SOP draft - homepage direction and CTA hierarchy are drafted, but site implementation is still pending +- the first content batch and paid SOP path now have execution specs in `docs/assets/` - a cross-project execution summary now exists in `docs/FinancialFreedomExecutionStack.md` Current gap summary: @@ -118,6 +119,11 @@ This layer is allowed, but it should finance the earlier layers rather than domi - [x] Add support for downloadable asset hooks such as checklists or templates - [ ] Create reusable asset-brief templates instead of only case-study briefs +Execution note: + +- first-batch execution plan: `docs/assets/FirstContentBatchExecutionPlan.md` +- first paid SOP path spec: `docs/assets/PaidSOPPathSpec.md` + ## Phase 4: Owned Capture - [x] Define one primary capture target: checklist download first @@ -138,6 +144,10 @@ Implementation note: - [ ] Define the first low-touch offer, only if needed as bootstrap revenue - [ ] Map which content types should lead to which monetization type +Current working paid asset: + +- `开源 AI 项目上线与基础加固 SOP` + ## Phase 6: Site Integration - [x] Keep `fzhang.dev` primarily as a content site diff --git a/docs/assets/FirstContentBatchExecutionPlan.md b/docs/assets/FirstContentBatchExecutionPlan.md new file mode 100644 index 000000000..86c261560 --- /dev/null +++ b/docs/assets/FirstContentBatchExecutionPlan.md @@ -0,0 +1,168 @@ +# 第一批可转化长尾内容执行计划 + +这份计划的目标不是继续罗列想法。 + +目标是: + +- 从现有 10 个 long-tail topics 中选出第一批真正要发的内容 +- 明确每篇内容服务于哪一段漏斗 +- 让每篇内容都为免费清单和后续付费 SOP 铺路 + +## 当前漏斗基线 + +当前默认路径: + +1. 长尾文章 +2. 免费清单 +3. 邮件订阅 / 后续跟进 +4. 付费 SOP / 模板 + +所以第一批内容必须满足两个条件: + +- 有明确搜索意图 +- 能自然引到 checklist 或 SOP + +## Batch 1 选题 + +### 1. 部署一个 GitHub 项目前,最应该先确认的 10 件事 + +当前状态: + +- 已有首发文章草稿 + +角色: + +- 漏斗入口主文 + +主要任务: + +- 承接最强搜索意图 +- 把“解释版 -> 执行版清单”关系讲清楚 + +主要 CTA: + +- `领取开源 AI 项目部署前检查清单` + +下一步承接: + +- checklist 下载 + +### 2. 为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? + +角色: + +- 问题放大型文章 + +主要任务: + +- 把“本地可跑 != 可上线”讲透 +- 引出部署顺序、环境差异、暴露面和回滚问题 + +主要 CTA: + +- `先用部署前检查清单过一遍` + +下一步承接: + +- checklist 下载 +- SOP 预告 + +### 3. 开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? + +角色: + +- checklist 到 SOP 的桥梁文 + +主要任务: + +- 让读者意识到“不是所有问题都要一次解决” +- 引出“基础加固 SOP” 的必要性 + +主要 CTA: + +- `先领清单` +- `如果你更关心上线与基础加固,留意后续 SOP` + +下一步承接: + +- checklist +- paid SOP waitlist / interest signal later + +### 4. 域名、HTTPS、反代、鉴权:第一次公开上线前最容易漏掉什么? + +角色: + +- 高执行细节文 + +主要任务: + +- 为 SOP 建立“更细、更实操”的预期 +- 开始把主题往 deployment + hardening cluster 收拢 + +主要 CTA: + +- `下载清单` + +下一步承接: + +- checklist +- future SOP + +## 发布顺序 + +推荐顺序: + +1. `部署一个 GitHub 项目前,最应该先确认的 10 件事` +2. `为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` +3. `开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?` +4. `域名、HTTPS、反代、鉴权:第一次公开上线前最容易漏掉什么?` + +原因: + +- 先吃最明确的搜索意图 +- 再放大问题 +- 再桥接到 SOP +- 再往更细执行主题推进 + +## 每篇内容的最小完成标准 + +每篇文章发布前都至少满足: + +- 有明确主关键词或问题句 +- 首屏能在 5 秒内说明这篇文章解决什么问题 +- 文中至少 1 次自然引到 checklist +- 文末至少 1 个明确 CTA +- 能进入 `deployment` / `launch readiness` / `hardening` 主题簇 + +## 每篇内容需要带出的证据 + +不要只看阅读量。 + +每篇文章至少要观察: + +- 页面访问 +- checklist 点击 +- checklist 提交 +- 订阅确认 +- 邮件回复 +- 是否有人问更深版本 + +## 不该优先写的内容 + +当前阶段不优先: + +- 纯热点评论 +- 泛 AI 观点文 +- 与部署、自托管、上线准备弱相关的内容 +- 很难自然连接 checklist 或 SOP 的主题 + +## Batch 1 之后的判断门槛 + +只有当下面这些信号开始重复出现,才说明可以继续加速 paid SOP 路径: + +- 多篇文章都能稳定带来 checklist 下载 +- 下载后有人回复具体上线问题 +- 有人明确询问更完整版本 +- 同类问题反复出现 + +如果这些信号不出现,就先继续优化主题与漏斗,不急着扩 product lane。 diff --git a/docs/assets/PaidSOPPathSpec.md b/docs/assets/PaidSOPPathSpec.md new file mode 100644 index 000000000..45451d50c --- /dev/null +++ b/docs/assets/PaidSOPPathSpec.md @@ -0,0 +1,161 @@ +# 第一个付费 SOP 路径规格 + +当前目标不是直接把 SOP 做成“大产品”。 + +当前目标是: + +- 把免费清单后的下一层付费资产定义清楚 +- 让后续文章、邮件和资源页知道该往哪里承接 + +## 付费资产名称 + +建议保留当前方向: + +- `开源 AI 项目上线与基础加固 SOP` + +## 它解决的核心问题 + +免费清单解决的是: + +- 我部署前该先检查什么 + +付费 SOP 要解决的是: + +- 我已经决定要部署了,接下来应该按什么顺序推进到“第一版可用、明显风险已收敛” + +## 它不是 + +这份付费 SOP 不是: + +- 企业级安全总方案 +- 全技术栈通用百科 +- 一次性解决所有上线问题的万能指南 +- 代替真实部署经验的捷径 + +## 它是 + +这份付费 SOP 应该是: + +- 执行顺序清晰 +- 决策优先级明确 +- 适合独立开发者和小团队 +- 能把“本地能跑”推进到“第一版可用”的低摩擦执行资产 + +## 最适合的购买人群 + +- 已经选定项目的人 +- 已经准备动手部署的人 +- 不想靠盲试推进第一版的人 +- 想先收敛明显风险、但又不想一上来做重安全工程的人 + +## 与免费清单的关系 + +不要让免费清单和 SOP 互相打架。 + +正确关系应该是: + +- 免费清单:部署前判断与核对 +- 付费 SOP:部署中的顺序与执行 + +一句话区分: + +- 清单帮你知道先看什么 +- SOP 帮你知道先做什么 + +## 付费 SOP 的核心卖点 + +### 1. 顺序感 + +很多人不是完全不会,而是不知道先做哪一步。 + +### 2. 边界感 + +很多人会在第一版上线前把自己拖死,因为默认必须一次做完。 + +### 3. 风险收敛 + +它不承诺完美,但能优先收掉最容易出事故的点。 + +### 4. 可复用 + +不是看完一次就废,而是下次部署别的项目还能继续参考。 + +## 推荐交付形式 + +第一版推荐: + +- Markdown / PDF SOP 正文 +- 一页执行总流程图 +- 一份上线前最后检查页 + +可以后续再扩: + +- Notion 版 +- Obsidian 版 +- 可打印版 + +## 当前最合理的价格实验 + +当前阶段不需要追求高客单价。 + +建议先把它当作: + +- 小额、低摩擦、验证型数字产品 + +推荐实验区间: + +- `¥39 - ¥99` + +目的不是利润最大化,而是验证: + +- 是否有人愿意为更完整版本付钱 +- 哪种文案和承接方式更能转化 + +## 最适合的销售路径 + +### 路径 A + +文章 -> checklist -> follow-up email -> SOP + +### 路径 B + +资源成功页 -> SOP waitlist / upcoming version signal + +### 路径 C + +专题邮件末尾轻量 mention -> SOP + +当前不推荐: + +- 首页硬卖 SOP +- 站点到处贴强销售 CTA + +## 付费 SOP 上线前必须满足的条件 + +至少满足其中大部分,再正式推出: + +- checklist 已真实跑通 +- 有稳定下载 +- 有后续邮件链路 +- 有人问更完整版本 +- 至少有 1 到 3 个真实问题反复出现 + +如果这些条件都没有,就先别急着大推。 + +## 需要补的销售资产 + +为了真正卖得动,这条路径后续至少还要补: + +- 一页 SOP 销售页文案 +- 一封 checklist 后的 SOP 预热邮件 +- 一封正式发布邮件 +- 一个“这份 SOP 适合谁 / 不适合谁”的说明页 + +## 当前下一步 + +不是继续抽象讨论,而是开始为 SOP 上线铺桥: + +1. 用 Batch 1 内容持续推 checklist +2. 在邮件里观察是否出现更深需求 +3. 根据真实问题补充 SOP 最核心章节 +4. 准备第一个轻量价格实验 diff --git a/docs/assets/README.md b/docs/assets/README.md index 6ca7d9261..a3df64e43 100644 --- a/docs/assets/README.md +++ b/docs/assets/README.md @@ -9,7 +9,9 @@ Current scope: - post-submit / follow-up copy - long-form article drafts - first-wave content topic clusters +- first batch execution plans - short-form content packs - SOP / template drafts +- paid SOP path specs These files are intentionally written as working assets, not just abstract strategy notes. From 77e6a120bf2a0358d034b747c6a6e890c69e49e0 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:16:33 +0800 Subject: [PATCH 15/27] Update email flow docs with Buttondown findings --- docs/FzhangEmailAutomationBlueprint.md | 247 +++++++++++++------------ docs/FzhangSiteAcceptanceAudit.md | 39 ++-- docs/Roadmap.md | 9 +- 3 files changed, 163 insertions(+), 132 deletions(-) diff --git a/docs/FzhangEmailAutomationBlueprint.md b/docs/FzhangEmailAutomationBlueprint.md index 4fb3d3a4b..a0b9c6ced 100644 --- a/docs/FzhangEmailAutomationBlueprint.md +++ b/docs/FzhangEmailAutomationBlueprint.md @@ -16,149 +16,169 @@ - 隐藏字段 `source_page=/resources/open-source-ai-deployment-checklist/` - 隐藏字段 `download=/downloads/open-source-ai-deployment-checklist.md` - 当前 `订阅` 页已经不是 RSS-only,而是邮件订阅 + RSS 双入口 -- 当前成功页已经显示“先确认邮箱,再送达清单”的 double opt-in 式引导 +- 当前成功页会把用户引导到确认邮箱的后续流程 +- 根据后续代码审查结果,当前资源本身是站内即时解锁,不是通过 Buttondown 邮件交付 这意味着: - 你已经有资源领取入口 -- 站点结构已经基本切换到成熟订阅路径 -- 但是否真的完成邮件送达、标签写入和自动序列,仍需要真实邮箱验收 +- 站点结构已经从“纯 RSS + 纯表单”升级成“站内资源领取 + Buttondown 订阅” +- 但当前不应误判为“完整自动化邮件系统已经全部落地” ## 当前验收结论 -根据线上页面检查,下面这些已经基本成立: +根据线上页面检查与后续代码审查结果,下面这些已经基本成立: - 资源页已明确区分公开文章与执行版资源 - 表单已切到自建接口而不是纯表单托管 - 订阅页已完成邮件 + RSS 双路径 -- 成功页已具备确认订阅与后续 digest 预期管理 +- 成功页已具备确认订阅与后续更新预期管理 +- 资源交付当前主要依赖站内即时解锁,不依赖 Buttondown 发“资源交付邮件” 还不能只靠浏览器确认的部分: - 确认邮件是否真实发出 -- 资源交付邮件是否真实发出 - 是否写入正确标签 -- 自动序列是否按时触发 -- 退订入口是否真实可用 +- Welcome 邮件是否已带管理订阅和退订入口 +- 低频分群发送是否按设计执行 所以当前状态更准确的说法是: -> 前端与信息架构已经明显升级,但邮件闭环仍需要真实邮箱验收。 +> 前端与信息架构已经明显升级,但当前更接近“站内即时交付 + Buttondown 订阅确认 + Welcome + 低频分群发送”,还不是完整的多步自动化邮件系统。 -## 推荐方案 +## 已确认的实现边界 -不要把“自动回信”理解成邮箱规则自动回复。 +根据你补充的检查结果,当前应按下面这套边界理解系统: -更成熟的做法是: +### 1. 确认邮件没有退订链接是正常现象 -`资源领取表单 -> 立即交付邮件 -> 进入订阅系统 -> 标签化 -> 自动序列 -> 周更或月更更新` +- 这是 Buttondown double opt-in 的确认步骤 +- 它不是正式 newsletter,也不是后续内容邮件 +- 在用户还没完成确认前,Buttondown 不把这次关系视为已激活订阅 -我建议你采用两层结构: +所以: -### 第一层:立即交付 +- 不应把“确认邮件里没有退订链接”视为 bug +- 不应花时间硬改确认邮件去补一个并不适配的退订入口 -负责把免费资源立刻发出去。 +### 2. 当前并不存在“资源交付邮件” -可选实现: +当前更准确的交付路径是: -- 继续使用 `Formspree` 自动回复 -- 或改成你自己的 serverless endpoint 发送事务型邮件 +- 用户提交资源表单 +- 站内即时解锁下载 +- 如果用户勾选或进入订阅路径,则再进入 Buttondown 订阅关系 -### 第二层:长期订阅 +这意味着: -负责后续更新、标签、分组和自动序列。 +- 资源本身不是通过 Buttondown welcome / automation / transactional 邮件交付 +- 不应继续把“资源交付邮件”当成当前系统的既有事实 -我建议优先用 `Buttondown`,原因是它更贴近你的博客形态: +### 3. 当前真正存在的邮件职责 -- 支持标签与自动化 -- 支持 RSS-to-email -- 适合内容站而不是纯销售漏斗站 -- 支持自定义嵌入表单和 metadata +当前应区分为: -## 为什么不建议只靠 Formspree +- `Confirmation Email` + - 负责确认订阅 +- `Welcome Email` + - 负责说明订阅了什么 + - 负责告诉用户先看什么 + - 负责提供管理订阅和退订入口 +- 后续低频分群发送 + - 只在 deployment 主题下有新资源、新 SOP、重要相关文章时再发 -`Formspree` 适合做表单接收和简单自动回复,但不适合作为长期订阅系统。 +## 当前最合理的运行模型 -原因: +当前最符合现实、且对 Frank 负担最低的模型不是“多步全自动 drip”,而是: -- 它不是完整的 newsletter / subscriber system -- 后续更新、标签、自动序列、分群都不够自然 -- 你最终还是会需要一个专门的订阅平台 +`资源页 -> API -> Buttondown subscriber + tags -> confirmation -> welcome email -> 按 topic-deployment 低频分群发送` -## 为什么更适合 Buttondown +这套模型的特点是: -根据 Buttondown 官方文档,它支持: +- 资源继续站内即时交付 +- 邮件只承担订阅关系和后续更新 +- 当前先不强行上复杂 CRM 或重自动化 +- 后续如果方案升级,再补 2 到 3 封 follow-up 或 RSS digest -- 通过 API 创建 subscriber -- 通过标签做分群 -- 基于 subscriber confirmed 等触发器做 automations -- 基于 RSS 自动发送站点更新 +## 推荐方案 -这和你当前的站点结构是匹配的: +不要把“自动回信”理解成邮箱规则自动回复。 -- 你本来就有 RSS -- 你的网站本来就是内容站 -- 你后续需要的是“围绕主题的持续更新”,不是一次性表单通知 +更成熟的做法是: -## 两种落地路径 +`资源领取 -> 站内即时交付 -> 进入订阅系统 -> 标签化 -> Welcome 邮件 -> 低频主题更新` -### 路径 A:最快可用 +我建议你采用两层结构: -保留当前 `Formspree` 表单。 +### 第一层:资源交付 -实现方式: +负责把免费资源立刻交付给用户。 -1. 开启 `Formspree` 自动回复,立即发送清单 -2. 如果你的 Formspree 计划支持 Webhooks,把提交同步到 `Buttondown` -3. 在 Buttondown 里创建标签、自动序列和 RSS-to-email +当前最省力的实现: -优点: +- 继续保留站内即时解锁 +- 不把免费资源强行改成邮件附件或邮件下载链接 -- 改动最小 -- 站点前端几乎不用大改 +原因: -缺点: +- 维护成本最低 +- 用户拿资源最快 +- 不会把 welcome 邮件错误地承担成“资源交付邮件” -- 对 Formspree 计划有依赖 -- 数据链路拆成两段 +### 第二层:长期订阅 -### 路径 B:更干净的长期方案 +负责后续更新、标签、分组和少量自动化。 + +我建议优先用 `Buttondown`,原因是它更贴近你的博客形态: -把表单提交改到你自己的 serverless endpoint。 +- 支持标签与自动化 +- 支持 RSS-to-email +- 适合内容站而不是纯销售漏斗站 +- 支持自定义嵌入表单和 metadata -推荐部署位置: +## 为什么当前不急着上更重的自动化 -- Cloudflare Workers -- Vercel Functions +当前更重要的不是把系统做复杂,而是把现实链路跑稳。 -服务分工: +当前不建议优先投入的方向: -- Turnstile 继续做人机校验 -- 你的 endpoint 接收表单 -- endpoint 发送一封事务型资源交付邮件 -- endpoint 再把订阅者写入 Buttondown +- 为了 2 到 3 封 follow-up 额外接 Zapier / Make +- 为了显得先进而上复杂 CRM +- 对所有新文章做自动逐篇群发 +- 把弱相关文章也硬塞给 `topic-deployment` 订阅者 -优点: +## 为什么更适合 Buttondown -- 你完全掌控数据和流程 -- 不依赖 Formspree 的 webhook 计划 -- 后续接更多资源、更多标签、更多序列更稳 +根据 Buttondown 官方文档与当前代码审查结果,它支持: -缺点: +- 通过 API 创建 subscriber +- 通过标签做分群 +- 基于 tags 做分群 +- 在升级方案后再使用 automations / RSS-to-email -- 需要一次真正的工程实现 +这和你当前的站点结构是匹配的: -## 我建议你选哪条 +- 你本来就有 RSS +- 你的网站本来就是内容站 +- 你后续需要的是“围绕主题的持续更新”,不是高频运营系统 -如果你想最快上线: +## 当前最推荐的落地路径 -- 先走 `路径 A` +当前阶段最推荐的路径已经不是“二选一设计题”,而是: -如果你准备认真把站点做成长期内容资产系统: +1. 保留资源页即时解锁 +2. 保留 API 写入 Buttondown + tags +3. 保留 confirmation +4. 把 Welcome Email 做完整 +5. 后续只按 `topic-deployment` 做低频分群发送 +6. 以后如果付费升级,再接 2 到 3 封 follow-up 或 RSS digest -- 直接走 `路径 B` +这条路径的优点: -我更推荐 `路径 B`,因为它更接近成熟订阅方案,也更符合你后续会继续扩资源、扩标签、扩自动化的方向。 +- 最低维护成本 +- 符合你当前免费方案的能力边界 +- 不需要额外引入重运营工具 +- 能先把“主题订阅关系”跑稳 ## 推荐的数据模型 @@ -172,12 +192,14 @@ - `interest_topic` - `submitted_at` -推荐标签: +当前已知关键标签: - `lead-magnet` - `resource-checklist` - `topic-deployment` - `source-fzhang-dev` +- `site-updates` +- `owned-audience` 如果后续还会有别的资源,再继续扩: @@ -188,71 +210,68 @@ ### 最成熟的处理方式 -1. 用户提交表单 -2. 立即收到“资源交付邮件” -3. 同时进入“邮件订阅确认流程” -4. 只有确认后,才进入后续更新流 +1. 用户提交资源表单 +2. 资源在站内即时交付 +3. 如果用户进入订阅路径,则收到确认邮件 +4. 确认后收到 Welcome Email +5. 之后只在 deployment 主题下有真正值得发的更新时,再低频分群发送 -这比“提交后直接把人扔进长期群发”更成熟,原因是: +这比“提交后直接把人扔进长期群发”更适合当前阶段,原因是: - 更合规 -- 更少垃圾地址 -- 打开率更高 -- 长期列表质量更好 +- 保持订阅质量 +- 降低运营负担 +- 不会为了自动化而自动化 -## 推荐的自动邮件结构 +## 当前推荐的邮件结构 -### Email 1:资源交付 +### Email 1:Confirmation Email 触发: -- 表单提交成功后立即发送 +- 用户提交订阅后立即发送 目的: -- 把资源交付出去 -- 明确“解释版 vs 执行版”的差异 -- 给一个低摩擦下一步 +- 完成 double opt-in 确认 -核心内容: +边界: -- 下载链接 -- 一句使用建议 -- 一篇相关文章入口 +- 不必强求退订链接 +- 不应被误判为正式 newsletter +- 只需完成确认动作 -### Email 2:使用提醒 +### Email 2:Welcome Email 触发: -- 订阅确认后 2 天 +- 用户确认订阅后 目的: -- 提高资源实际打开率 -- 告诉读者什么时候应该打开这份清单 +- 说明订阅了什么 +- 告诉用户先看什么 +- 给出主题预期 +- 显式提供管理订阅和退订入口 -### Email 3:主题深化 - -触发: - -- 订阅确认后 5 到 7 天 - -目的: +建议正文必须包含: -- 引到更完整的 SOP 方向 -- 观察真实需求反馈 +- `{{ manage_subscription_url }}` +- `{{ unsubscribe_url }}` +- 一条起步阅读入口 +- 一条关于后续发送节奏的说明 -### Email 4 之后:站点更新 +### Email 3 之后:低频主题更新 触发: -- 周更 digest 或按 RSS 生成的更新邮件 +- Frank 真的发了 deployment 主题下值得发的新资源、新 SOP、重要相关文章或主题汇总 建议: -- 不要每篇文章都即时轰炸 -- 优先周更 -- 后续如果能按 tag 发,只给部署相关订阅者发对应内容更好 +- 当前不做所有文章自动逐篇发 +- 当前优先低频、分群、主题相关 +- 如果未来升级,再加 fixed cadence 的 digest 或 follow-up automation ## 你的站点应该怎么改 diff --git a/docs/FzhangSiteAcceptanceAudit.md b/docs/FzhangSiteAcceptanceAudit.md index cd4201508..ce57c0e0e 100644 --- a/docs/FzhangSiteAcceptanceAudit.md +++ b/docs/FzhangSiteAcceptanceAudit.md @@ -9,7 +9,7 @@ - 实际访问线上站点 - 检查资源页、订阅页、成功页 - 检查前端表单字段与提交目标 -- 不做真实邮箱提交,因此不包含邮件送达层的最终验收 +- 结合后续代码审查结果修正邮件链路判断 ## 验收范围 @@ -70,17 +70,29 @@ 这已经接近成熟订阅方案的结构。 +### 5. 代码审查已澄清当前交付边界 + +后续检查结果显示: + +- 当前资源本身不是靠邮件交付 +- 当前更接近“站内即时解锁 + Buttondown 订阅确认 + Welcome + 低频分群发送” + +这意味着: + +- 之前把它描述成“资源交付邮件 + 完整自动序列”并不准确 +- 当前更现实的验收重点应该是确认邮件、Welcome 邮件、标签和低频分群逻辑 + ## 风险与未完成项 -### 1. 邮件送达链路仍未做真实邮箱验收 +### 1. 邮件链路仍需最终按现实边界验收 目前还不能从浏览器侧证明以下事项已经真实成立: - 是否确实发出了确认邮件 -- 是否确实发出了资源交付邮件 -- 是否确实进入了自动序列 +- Welcome 邮件是否真实发出 - 是否确实写入了正确标签 -- 是否每封邮件都带退订入口 +- Welcome 邮件是否带管理订阅 / 退订入口 +- 后续低频分群发送是否按预期执行 这些必须用真实测试邮箱完整跑一遍才能算通过。 @@ -109,17 +121,16 @@ 用一个全新测试邮箱,完整跑下面一遍: 1. 在资源页提交邮箱 -2. 确认是否收到确认邮件 -3. 点击确认链接 -4. 确认是否收到资源交付邮件 -5. 确认下载链接是否可用 -6. 检查邮件里是否有: +2. 确认资源是否站内即时可得 +3. 确认是否收到确认邮件 +4. 点击确认链接 +5. 确认是否收到 Welcome 邮件 +6. 检查 Welcome 邮件里是否有: - 退订入口 - 品牌一致的发件人 - 合理的文案节奏 -7. 2 天后检查第二封邮件是否按计划触发 -8. 5 到 7 天后检查第三封邮件是否按计划触发 -9. 在订阅系统后台检查是否已打上正确标签 +7. 在订阅系统后台检查是否已打上正确标签 +8. 等下一次 deployment 主题更新时,检查是否按分群逻辑低频发出 ## 当前结论 @@ -129,4 +140,4 @@ 如果看完整业务闭环: -- 还差最后一步:真实邮箱验收 +- 还差最后一步:按当前真实实现边界完成最终邮箱验收 diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 94a6a63ac..f50408fc6 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -38,7 +38,7 @@ Current gap summary: - measurement is not wired yet - topic scoring is not implemented yet - affiliate-safe comparison / recommendation clusters are not defined yet -- email delivery, tagging, and sequence timing still need true inbox verification +- welcome email, unsubscribe visibility, tagging, and low-frequency topic sends still need final verification ## North Star @@ -128,13 +128,14 @@ Execution note: - [x] Define one primary capture target: checklist download first - [ ] Add CTA variants that point to owned capture instead of direct call booking -- [ ] Turn resource capture into a mature email path instead of one-off form replies +- [ ] Turn resource capture and subscription follow-up into a stable, low-overhead email path - [ ] Add measurement for capture conversion by topic type Implementation note: - live site now uses a custom `/api/subscribe` endpoint for the checklist flow -- success page already frames the flow as confirmation-first, then resource delivery +- current reality is `site unlock + Buttondown confirmation + welcome + low-frequency topic sends` +- resource delivery is not primarily email-driven in the current implementation - still needs real inbox verification before this phase item can be closed ## Phase 5: Monetization Experiments @@ -211,7 +212,7 @@ If the answer to 1-3 is "no", it is probably off-strategy. ## Executable Shortlist 1. Upgrade the checklist landing page so visitors immediately understand it is an execution asset, not a gated copy of a public article. -2. Ship the first real email capture system: immediate resource delivery, confirmed follow-up sequence, and ongoing site updates. +2. Stabilize the first real owned-audience path: confirmation, welcome email, visible subscription management, and low-frequency topic sends. 3. Add first-pass measurement for the checklist funnel: page views, submits, confirmed subscribers, and downstream clicks. ## Portfolio Rule From f5abfc0dd79c5c6e42b974e59afc05a4ac7feee8 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:21:34 +0800 Subject: [PATCH 16/27] Align docs with actual Buttondown flow --- docs/FinancialFreedomExecutionStack.md | 2 +- ...zhangButtondownFollowupAutomationPrompt.md | 26 +++++--- .../FzhangButtondownUnsubscribeAuditPrompt.md | 15 ++--- ...FzhangChecklistSiteImplementationPrompt.md | 9 +++ docs/FzhangEmailAutomationBlueprint.md | 59 ++++++++++--------- docs/assets/PaidSOPPathSpec.md | 2 +- 6 files changed, 66 insertions(+), 47 deletions(-) diff --git a/docs/FinancialFreedomExecutionStack.md b/docs/FinancialFreedomExecutionStack.md index 5f5fb3b18..a4c453da4 100644 --- a/docs/FinancialFreedomExecutionStack.md +++ b/docs/FinancialFreedomExecutionStack.md @@ -246,7 +246,7 @@ This means: - true email delivery verification - tagging and sequence verification -- resource delivery verification +- resource unlock / welcome flow verification - basic measurement ### Priority 2: Publish monetizable long-tail content diff --git a/docs/FzhangButtondownFollowupAutomationPrompt.md b/docs/FzhangButtondownFollowupAutomationPrompt.md index 40c8ed1b6..ddd1ee61c 100644 --- a/docs/FzhangButtondownFollowupAutomationPrompt.md +++ b/docs/FzhangButtondownFollowupAutomationPrompt.md @@ -16,8 +16,8 @@ 之后希望实现: -- 先发资源交付邮件 -- 再发少量后续邮件 +- 资源先站内即时解锁 +- 再发少量订阅后续邮件 - 后续如果这条主题下扩展出新文章、资源、SOP,也能优先发给这批人 但前提是: @@ -26,7 +26,7 @@ - 不能每发一篇内容就手工给这批人发一封 - 不能把整个系统做成很重的 CRM -## 你必须先核对的 Buttondown 官方能力 +## 你必须先核对的 Buttondown 官方能力与计划边界 请检查并利用这些能力: @@ -41,6 +41,11 @@ - 每月汇总发 - Create subscriber API 默认 double opt-in +同时请核对一个现实前提: + +- 当前 Frank 使用的 Buttondown 方案不一定已经包含 `Automations` 或 `RSS-to-email` +- 请不要把付费功能当作已可用能力直接假设 + ## 当前判断方向 请围绕下面这个判断做验证或修正: @@ -51,9 +56,10 @@ 1. 提交资源表单 2. double opt-in 确认 -3. 立即收到资源交付邮件 -4. 再进入一个短 welcome / nurture sequence -5. 后续通过 RSS-to-email 或定期 digest 自动接收相关更新 +3. 资源站内即时解锁 +4. 确认后收到 Welcome 邮件 +5. 后续按 `topic-deployment` 做低频分群发送 +6. 如果未来升级方案,再补 short welcome sequence 或 RSS digest 这比: @@ -85,8 +91,9 @@ 我更偏向的目标是: -- 资源领取后 2 到 3 封自动后续邮件 -- 之后进入主题相关的 digest 更新 +- 当前先跑稳 `confirmation + welcome + 低频分群发送` +- 以后若升级能力,再加 2 到 3 封自动后续邮件 +- 之后再考虑主题相关的 digest 更新 - 不做高频手工运营 ### 任务 3:设计标签与过滤逻辑 @@ -117,7 +124,7 @@ 例如: -`资源页 -> API -> Buttondown subscriber + tags -> confirmation -> welcome/resource email -> 2-step follow-up -> weekly RSS digest` +`资源页 -> 站内即时解锁 -> API -> Buttondown subscriber + tags -> confirmation -> welcome email -> 按 topic-deployment 低频分群发送` ## 输出要求 @@ -147,4 +154,5 @@ - 不要默认推荐复杂 CRM - 不要把“后续优先发给我”设计成必须人工一封一封维护 +- 不要把“资源站内即时交付”误写成“必须邮件交付” - 优先给出“当前阶段够用、未来可扩展”的方案 diff --git a/docs/FzhangButtondownUnsubscribeAuditPrompt.md b/docs/FzhangButtondownUnsubscribeAuditPrompt.md index 07d2dbd85..0cbc2670a 100644 --- a/docs/FzhangButtondownUnsubscribeAuditPrompt.md +++ b/docs/FzhangButtondownUnsubscribeAuditPrompt.md @@ -12,7 +12,8 @@ - 资源页和订阅页都已切到自建 `/api/subscribe` - 新订阅者会收到确认邮件 -- 确认后会收到资源交付邮件 +- 资源本身当前是站内即时解锁,不是通过邮件交付 +- 确认后应进入 Welcome / 后续订阅关系,而不是“资源交付邮件” - Buttondown 后台可以看到订阅者信息变化 - 但用户现在看不到明确的退订链接 @@ -40,9 +41,9 @@ 你要明确区分: - 确认邮件为什么可能天然没有退订链接 -- 资源交付邮件为什么理论上应该有退订或管理入口 +- 当前 Welcome / 后续主题邮件为什么应该有退订或管理入口 -### 任务 2:检查当前站点链路里,资源交付邮件到底属于哪一类 +### 任务 2:检查当前站点链路里,Welcome / 后续邮件到底属于哪一类 判断它是: @@ -64,7 +65,7 @@ 至少包含: 1. 是否开启 Buttondown Portal -2. 是否在 welcome / resource delivery 邮件正文里显式加入: +2. 是否在 welcome / 后续主题邮件正文里显式加入: - `{{ unsubscribe_url }}` - `{{ manage_subscription_url }}` 3. 确认邮件里如果不能提供退订链接,应该用什么替代文案降低困惑 @@ -76,11 +77,11 @@ - 新邮箱首次订阅 - 收到确认邮件 -- 确认后收到资源交付邮件 +- 确认后收到 Welcome 邮件 - 邮件正文是否有订阅管理入口 - footer 是否自动出现 - 点击后能否进入管理 / 退订页面 -- 旧订阅者再次领取资源时是否仍能看到订阅管理入口 +- 旧订阅者后续再收到主题邮件时是否仍能看到订阅管理入口 ## 输出要求 @@ -108,4 +109,4 @@ - 不要建议“手动回复用户完成退订” - 不要把“没有退订链接”简单归因于前端问题 -- 要明确区分确认邮件、欢迎邮件、资源交付邮件、普通更新邮件的责任边界 +- 要明确区分确认邮件、欢迎邮件、站内资源交付、普通更新邮件的责任边界 diff --git a/docs/FzhangChecklistSiteImplementationPrompt.md b/docs/FzhangChecklistSiteImplementationPrompt.md index ce679601e..dfbd806b6 100644 --- a/docs/FzhangChecklistSiteImplementationPrompt.md +++ b/docs/FzhangChecklistSiteImplementationPrompt.md @@ -1,5 +1,14 @@ # 给另一个 AI 的站点改造提示词 +> Historical note: +> this prompt was written before the current site implementation landed. +> Treat it as an archive of the original build brief, not as the current source of truth. +> For current email / subscription reality, prefer: +> - `docs/FzhangEmailAutomationBlueprint.md` +> - `docs/FzhangSiteAcceptanceAudit.md` +> - `docs/FzhangButtondownUnsubscribeAuditPrompt.md` +> - `docs/FzhangButtondownFollowupAutomationPrompt.md` + 你现在要修改 `fzhang.dev` 的站点源码。不要泛泛给建议,直接完成实现。 ## 背景 diff --git a/docs/FzhangEmailAutomationBlueprint.md b/docs/FzhangEmailAutomationBlueprint.md index a0b9c6ced..bfe21781a 100644 --- a/docs/FzhangEmailAutomationBlueprint.md +++ b/docs/FzhangEmailAutomationBlueprint.md @@ -297,31 +297,31 @@ 这样不会破坏你喜欢 RSS 的站点气质,同时也能承接资源用户。 -## 实现步骤 - -### 方案 A:Formspree + Buttondown - -1. 在 Formspree 开启 autoresponse -2. 交付第一封资源邮件 -3. 若你的 Formspree 计划支持 Webhooks,则配置 webhook -4. webhook 把 `email/name/resource/source_page` 发到你的同步服务 -5. 同步服务调用 Buttondown API,创建 subscriber 并打标签 -6. 在 Buttondown 中创建: - - welcome / nurture automation - - RSS-to-email automation - -### 方案 B:Serverless + Buttondown - -1. 前端表单发到 `/api/resource-signup` -2. 后端验证 Turnstile -3. 后端发送资源交付邮件 -4. 后端调用 Buttondown API 创建 subscriber -5. subscriber 打上: - - `lead-magnet` - - `resource-checklist` - - `topic-deployment` - - `source-fzhang-dev` -6. Buttondown 负责后续 automation 和 RSS-to-email +## 当前实现步骤 + +### 当前现实链路 + +1. 用户提交资源页表单 +2. 资源在站内即时解锁 +3. 站点 API 把订阅者写入 Buttondown +4. 订阅者完成 confirmation +5. Buttondown 发送 Welcome Email +6. 后续只在 deployment 主题下有真正值得发的更新时,再低频分群发送 + +### 未来升级步骤 + +只有在下面任一条件成立时,再考虑升级: + +- 你确认当前 Buttondown 计划已包含 automations +- 你确认当前 Buttondown 计划已包含 RSS-to-email +- checklist funnel 已稳定跑通,且你真的需要更固定的 cadence + +升级方向: + +1. 保留站内即时解锁,不改回邮件交付 +2. 在 Welcome 之后补 2 到 3 封 short follow-up +3. 或对 `topic-deployment` 订阅者开启 weekly / digest 更新 +4. 仍避免对所有零散文章做自动逐篇发送 ## 关键优化点 @@ -344,18 +344,19 @@ RSS 应该保留,但不该继续独占“订阅”入口。 -### 4. 把资源交付和长期订阅分层 +### 4. 把站内交付和长期订阅分层 这是成熟方案最重要的区别之一。 -- 资源交付邮件:事务型 +- 资源交付:站内即时完成 - 后续更新邮件:订阅型 ## 官方文档依据 -- Formspree autoresponse: https://help.formspree.io/hc/en-us/articles/360025007233-Sending-a-confirmation-or-response-email -- Formspree webhooks: https://help.formspree.io/hc/en-us/articles/360015234873-Webhooks - Buttondown automations: https://docs.buttondown.com/automations-introduction - Buttondown create subscriber API: https://docs.buttondown.com/api-subscribers-create - Buttondown RSS-to-email: https://docs.buttondown.com/rss-to-email - Buttondown subscriber base / embed form / metadata: https://docs.buttondown.com/building-your-subscriber-base +- Buttondown confirmation email: https://docs.buttondown.com/transactional-emails-confirmation +- Buttondown welcome email: https://docs.buttondown.com/transactional-emails-welcome +- Buttondown portal: https://docs.buttondown.com/portal diff --git a/docs/assets/PaidSOPPathSpec.md b/docs/assets/PaidSOPPathSpec.md index 45451d50c..9a60909e4 100644 --- a/docs/assets/PaidSOPPathSpec.md +++ b/docs/assets/PaidSOPPathSpec.md @@ -115,7 +115,7 @@ ### 路径 A -文章 -> checklist -> follow-up email -> SOP +文章 -> checklist -> welcome / 低频主题邮件 -> SOP ### 路径 B From ad650cad6de1b3936dc4aac4acdba21e54cbc9a2 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:04:14 +0800 Subject: [PATCH 17/27] Document shop payment architecture decision --- AGENTS.md | 2 + docs/FinancialFreedomExecutionStack.md | 32 +++ docs/Roadmap.md | 8 + docs/ShopPaymentArchitecture.md | 285 +++++++++++++++++++++++++ 4 files changed, 327 insertions(+) create mode 100644 docs/ShopPaymentArchitecture.md diff --git a/AGENTS.md b/AGENTS.md index db660cca8..3a295f23b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,7 @@ - `docs/FirstAssetSpec.md` - `docs/FinancialFreedomPath.md` - `docs/FzhangHomepageCopy.md` + - `docs/ShopPaymentArchitecture.md` ## Cross-Project Financial Freedom Context - This repo should be evaluated as one lane inside Frank's broader financial-freedom system, not in isolation. @@ -30,6 +31,7 @@ - `/Users/frank_zhang/Documents/文稿 - Frank's MacBook Air/Github项目/paperclip/doc/plans/2026-03-31-paperclip-financial-freedom-positioning.md` - `/Users/frank_zhang/Library/Mobile Documents/com~apple~CloudDocs/Obsidian 库/5.知识库/07个人成长/08财务自由之路/1当前财务自由系统的项目分工与顺序(2026-03-31).md` - When work touches monetization order, project prioritization, `fzhang.dev`, asset funnels, paid SOPs/templates, bootstrap services, or possible `paperclip` integration, consult the references above before making strategic changes. +- When work touches `shop.fzhang.dev`, payment processors, subscriptions, refunds, billing, entitlement sync, or order mirrors, consult `docs/ShopPaymentArchitecture.md` first. - Current cross-project operating model: - `cash flow survival layer + asset compounding layer + product optionality layer` - `MoneyPrinterV2` is the current main execution repo for the asset-compounding layer. diff --git a/docs/FinancialFreedomExecutionStack.md b/docs/FinancialFreedomExecutionStack.md index a4c453da4..b1bfe9ddf 100644 --- a/docs/FinancialFreedomExecutionStack.md +++ b/docs/FinancialFreedomExecutionStack.md @@ -110,6 +110,27 @@ Its job is to: - convert some readers into subscribers or downloaders - support later monetization pages +### `shop.fzhang.dev` + +Primary role: + +- checkout surface +- entitlement trigger surface +- monetization surface for paid digital assets + +Its job is not to become a full custom billing platform first. + +Its job is to: + +- let the right readers buy paid assets with low friction +- hand payment / billing complexity to a payment platform where possible +- mirror orders and access into Frank's own database and admin tooling + +Current rule: + +- do not use `Payoneer receiving account` as the primary checkout solution +- prefer a billing platform plus internal order / entitlement mirror model + ### Knowledge Base Primary role: @@ -213,6 +234,17 @@ The current recommended order is: 5. low-touch productized help only if useful as bootstrap revenue 6. larger software product only after strong repeated proof +### Payment Architecture Rule + +For paid digital assets sold through `shop.fzhang.dev`: + +- payment platform = source of truth for payment, billing, refunds, and subscriptions +- internal database = mirror for user mapping, entitlement, order state, and unlock state + +Do not invert this into: + +- self-built order truth with `Payoneer receiving account` as the main checkout layer + This order should come before: - broad service expansion diff --git a/docs/Roadmap.md b/docs/Roadmap.md index f50408fc6..a9e4eb7e8 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -39,6 +39,7 @@ Current gap summary: - topic scoring is not implemented yet - affiliate-safe comparison / recommendation clusters are not defined yet - welcome email, unsubscribe visibility, tagging, and low-frequency topic sends still need final verification +- `shop.fzhang.dev` payment architecture is now decided in principle, but not yet implemented in code ## North Star @@ -142,6 +143,7 @@ Implementation note: - [ ] Define the first affiliate-safe topic cluster - [x] Define the first paid digital asset to test +- [x] Decide the payment architecture principle for `shop.fzhang.dev` - [ ] Define the first low-touch offer, only if needed as bootstrap revenue - [ ] Map which content types should lead to which monetization type @@ -149,6 +151,12 @@ Current working paid asset: - `开源 AI 项目上线与基础加固 SOP` +Current payment architecture rule: + +- `shop.fzhang.dev` should use a payment / billing platform plus internal order mirror model +- do not use `Payoneer receiving account` as the primary checkout solution +- current preferred direction is `Paddle` first, `Lemon Squeezy` second, `Stripe` later if deeper control becomes necessary + ## Phase 6: Site Integration - [x] Keep `fzhang.dev` primarily as a content site diff --git a/docs/ShopPaymentArchitecture.md b/docs/ShopPaymentArchitecture.md new file mode 100644 index 000000000..65f605eac --- /dev/null +++ b/docs/ShopPaymentArchitecture.md @@ -0,0 +1,285 @@ +# shop.fzhang.dev 支付架构决策 + +这份文档用于冻结当前阶段关于 `shop.fzhang.dev` 支付与订单系统的判断。 + +它的目标不是比较所有支付工具。 + +它的目标是: + +- 避免把 `Payoneer receiving account` 误当成独立站 checkout 方案 +- 固定一套更适合数字产品 / SOP / 模板 / 订阅型资产的架构思路 +- 让后续在 `shop.fzhang.dev` 或相关仓库里开发时有统一参考 + +## 当前结论 + +### 不推荐 + +不建议把: + +- `Payoneer receiving account` + +当作 `shop.fzhang.dev` 的主 checkout / 主支付网关。 + +### 推荐 + +推荐采用: + +- `Stripe / Lemon Squeezy / Paddle` 这类支付 / 订阅 / 账单平台 +- 自己的数据库只负责: + - 用户映射 + - 权限状态 + - 订单镜像 + - 订阅镜像 + - 内容解锁状态 + - 操作后台 + +一句话: + +> 支付平台负责收钱、订阅、账单、退款;你自己的系统负责用户、权限和内容交付。 + +## 为什么不建议用 Payoneer receiving account 直接做独立站支付 + +根据 Payoneer 官方帮助中心: + +- `Request a Payment` 适合向 business clients 发收款请求 +- 但官方明确写了: + - 它 `does not support payments from consumers paying in your online store` + - 它 `is not meant to be used as a payment gateway (checkout) for your ecommerce store` +- `Receiving accounts` 更像本地 / 国际银行收款信息,用于: + - 客户打款 + - marketplace / 平台打款 + - 类似银行转账收款 + +这意味着: + +- 它更像 payout / bank transfer rail +- 不像一个成熟的独立站 checkout stack +- 它不适合作为数字产品、订阅、退款、账单、订单自助管理的主入口 + +## 为什么更适合用 Stripe / Lemon Squeezy / Paddle 这类架构 + +这些平台的共同点是: + +- 支持 checkout +- 支持 one-time orders 或 subscriptions +- 支持 refunds / billing / invoices +- 支持 webhooks +- 能让你把自己的数据库当成“业务镜像”,而不是支付真相源 + +这和你刚提到的理想架构是一致的: + +- 支付平台负责: + - payment + - subscription lifecycle + - invoicing + - refunds + - customer billing actions +- 你自己的数据库负责: + - user mapping + - entitlement state + - order mirror + - unlock state + - admin operations + +## 当前最推荐的方向 + +### 默认推荐 + +如果 `shop.fzhang.dev` 近期卖的是: + +- SOP +- 模板 +- 数字资源包 +- 轻量订阅 + +那么当前更推荐优先走: + +- `Merchant of Record` 路线 + +也就是: + +- `Paddle` 或 `Lemon Squeezy` + +而不是先自己承担更多支付合规和订单复杂度。 + +### 为什么 + +对当前阶段的 Frank 来说,最重要的不是“支付层最大控制权”,而是: + +- 低维护负担 +- 能尽快卖出第一个数字资产 +- 不把有限执行预算过早耗在账单、退款、税务、订阅管理细节上 + +## Paddle / Lemon / Stripe 的当前判断 + +### `Paddle` + +更适合的情况: + +- 你预计会更快进入 subscription / billing-heavy 路线 +- 你希望 customer portal、取消订阅、账单管理尽量少自己搭 +- 你希望 webhook 驱动数据库镜像和权限同步 + +根据 Paddle 官方文档: + +- customer portal 默认可用 +- Paddle 邮件会带 customer portal 链接 +- 适合把核心 billing workflow 交给 Paddle +- webhook provisioning 模型和“数据库镜像 + 权限同步”天然匹配 + +### `Lemon Squeezy` + +更适合的情况: + +- 你更偏 creator-style 的数字产品 +- 更重 one-time digital products,同时保留订阅可能 +- 你想要 hosted portal / my orders / downloadable files 这类现成功能 + +根据 Lemon Squeezy 官方文档: + +- 提供 customer portal +- 提供 my orders +- 作为 merchant of record 处理支付相关责任 + +### `Stripe` + +更适合的情况: + +- 你未来明确需要更深的定制化 billing 流程 +- 你愿意承担更高的系统设计与运营复杂度 +- 你希望长期保留最大控制权 + +根据 Stripe 官方文档: + +- 可管理 subscriptions +- 可管理 refunds +- 可自动生成 invoices +- 有 hosted customer portal + +但当前阶段: + +- Stripe 更像“能力最强的底层积木” +- 不一定是“最省执行预算”的第一选择 + +## 当前建议的最终判断 + +### 1. 支付架构原则 + +采用: + +- `支付平台作为支付真相源` +- `自有数据库作为业务镜像和权限系统` + +不要采用: + +- `自建订单系统 + Payoneer 直接收款` 作为主路径 + +### 2. Payoneer 的角色 + +当前更适合把 Payoneer receiving account 视为: + +- payout rail +- B2B 银行转账收款方式 +- 特定客户 / 公司付款的补充渠道 + +不应视为: + +- 主 checkout +- 主 ecommerce payment gateway +- 主 subscription stack + +### 3. 近期 vendor 倾向 + +如果你接下来很快要上线 `shop.fzhang.dev` 来卖数字资产,我的当前建议是: + +- 优先评估 `Paddle` +- 次选 `Lemon Squeezy` +- `Stripe` 作为未来需要更深度定制时再考虑的方案 + +原因不是“Paddle 永远更强”,而是: + +- 当前更接近 subscription / portal / low-maintenance 目标 +- 更符合你现在“先卖出第一个数字资产,再逐步复杂化”的阶段 + +## 推荐系统边界 + +### 支付平台负责 + +- checkout +- subscriptions +- invoices +- refunds +- billing emails +- customer self-service billing actions + +### 你的数据库负责 + +- internal user id 与 external customer id 映射 +- product ownership / entitlement +- order mirror +- subscription status mirror +- unlock state +- admin queries / support lookup + +### 你的应用逻辑负责 + +- webhook signature verification +- entitlement updates +- unlock / revoke content +- support tooling +- analytics / topic ledger / monetization evidence + +## 当前最小实现建议 + +如果现在就要开始落地: + +1. 先选定一个支付平台,不要继续停留在 Payoneer 方案上 +2. 先把 one-time digital product + webhook mirror 跑通 +3. 再补 subscriptions / portal / cancellation flows +4. 最后再考虑更复杂的自定义后台或 billing abstraction + +## 这条决策对当前系统的影响 + +它意味着: + +- `MoneyPrinterV2` 继续负责资产与漏斗 +- `fzhang.dev` 继续负责 trust / traffic / capture +- `shop.fzhang.dev` 负责 checkout / monetization surface +- `Payoneer` 不承担独立站主支付网关角色 + +## 官方依据 + +### Payoneer + +- Request a payment - Information for Receivers +- How to receive funds to your Payoneer account + +核心依据: + +- Payoneer 官方明确说明 request a payment 不是给 ecommerce store 做 checkout 用的 +- receiving accounts 更偏银行收款 / marketplace 打款 + +### Stripe + +- Customers +- Customer Portal +- Refunds +- Subscription invoices + +### Lemon Squeezy + +- Merchant of Record +- Customer Portal +- My Orders +- Refunds and Chargebacks + +### Paddle + +- Customer Portal +- Handle provisioning and fulfillment +- Subscription cancellation +- Customer portal sessions + +## 当前一句话规则 + +> `shop.fzhang.dev` 的主支付方案应该是“支付平台 + 自有数据库镜像”,而不是 “Payoneer receiving account 直接做独立站 checkout”。` From d139dcb8e3292ffcd45aae53e765ec39e47cf78c Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:09:32 +0800 Subject: [PATCH 18/27] Document payment architecture and topic ledger spec --- docs/Roadmap.md | 5 + docs/TopicLedgerMeasurementSpec.md | 355 +++++++++++++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 docs/TopicLedgerMeasurementSpec.md diff --git a/docs/Roadmap.md b/docs/Roadmap.md index a9e4eb7e8..e917dce4d 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -32,6 +32,7 @@ The following work is already represented in committed docs or repo changes: - homepage direction and CTA hierarchy are drafted, but site implementation is still pending - the first content batch and paid SOP path now have execution specs in `docs/assets/` - a cross-project execution summary now exists in `docs/FinancialFreedomExecutionStack.md` +- a first-pass topic ledger / measurement spec now exists in `docs/TopicLedgerMeasurementSpec.md` Current gap summary: @@ -183,6 +184,10 @@ Direction note: - [ ] optional service conversations - [ ] Maintain a topic ledger of outputs vs downstream value +Execution note: + +- first-pass measurement spec: `docs/TopicLedgerMeasurementSpec.md` + ## Decision Filters Before adding any new feature, ask: diff --git a/docs/TopicLedgerMeasurementSpec.md b/docs/TopicLedgerMeasurementSpec.md new file mode 100644 index 000000000..4826e737c --- /dev/null +++ b/docs/TopicLedgerMeasurementSpec.md @@ -0,0 +1,355 @@ +# Topic Ledger & Measurement Spec + +This document defines the minimum viable evidence system for Frank's current asset-compounding loop. + +The goal is not "perfect analytics". + +The goal is: + +- make topic performance observable +- connect content outputs to downstream behavior +- avoid confusing activity with proof +- create a shared format that future project work can update consistently + +## Why This Exists + +The current strategy depends on evidence. + +That means each serious topic cluster must be tracked across the whole path: + +1. content published +2. asset CTA shown +3. capture triggered +4. subscriber created +5. replies / demand signals observed +6. paid interest or paid conversion observed later + +Without this, it is too easy to: + +- keep publishing without learning +- overestimate weak topics +- push paid assets before proof exists +- waste time on topics that do not move anyone deeper into the system + +## Scope + +This spec covers: + +- topic-level tracking +- asset-level tracking +- first-pass funnel tracking for the checklist path +- evidence needed to justify deeper SOP pushes + +This spec does not require: + +- a full analytics warehouse +- a complex attribution model +- perfect automation from day one + +## Primary Topic Cluster For Now + +The first serious cluster is: + +- `deployment / launch readiness / hardening` + +Initial content in scope: + +- `部署一个 GitHub 项目前,最应该先确认的 10 件事` +- `为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` +- `开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?` +- `域名、HTTPS、反代、鉴权:第一次公开上线前最容易漏掉什么?` + +Primary asset in scope: + +- `开源 AI 项目部署前检查清单` + +Primary paid asset in scope: + +- `开源 AI 项目上线与基础加固 SOP` + +## The Minimum Ledger + +Maintain one ledger row per serious topic output. + +At minimum, each row should track: + +- `date_published` +- `topic_cluster` +- `content_title` +- `content_type` +- `canonical_url` +- `primary_cta` +- `asset_target` +- `page_views` +- `cta_clicks` +- `asset_unlocks_or_downloads` +- `confirmed_subscribers` +- `replies_or_feedback` +- `product_interest_signals` +- `paid_conversions` +- `notes` + +## Recommended Ledger Columns + +### Identity + +- `topic_cluster` + - example: `deployment` +- `content_title` +- `content_type` + - allowed starter values: + - `article` + - `resource_page` + - `success_page` + - `short_pack` + - `email` + - `sales_page` +- `status` + - `draft` + - `published` + - `archived` + +### Funnel Mapping + +- `primary_problem` +- `search_intent_level` + - `high` + - `medium` + - `low` +- `primary_cta` + - example: + - `领取免费清单` + - `订阅更新` + - `了解 SOP` +- `asset_target` + - example: + - `deployment-checklist` + - `launch-hardening-sop` +- `next_step` + - what you expect the reader to do after this piece + +### Performance + +- `page_views` +- `cta_clicks` +- `asset_unlocks_or_downloads` +- `confirmed_subscribers` +- `welcome_email_opens` + - optional when available +- `welcome_email_clicks` + - optional when available +- `replies_or_feedback` +- `product_interest_signals` + - examples: + - asks for deeper version + - asks for checklist expansion + - asks for review / audit help +- `paid_conversions` + +### Quality Notes + +- `proof_summary` +- `what_worked` +- `what_failed` +- `next_iteration` + +## Minimum Definitions + +### Page Views + +Definition: + +- visits to the canonical article or resource page + +### CTA Clicks + +Definition: + +- clicks on the main asset CTA inside that content + +Current examples: + +- click from article to checklist page +- click from homepage to checklist page + +### Asset Unlocks Or Downloads + +Definition: + +- successful resource unlocks or downloads + +For the current site model, this is not "email delivery". +It is: + +- successful checklist access / unlock / download completion + +### Confirmed Subscribers + +Definition: + +- subscribers who completed confirmation + +This is more important than raw form submit count. + +### Replies Or Feedback + +Definition: + +- actual responses, emails, DMs, or comments that show someone engaged with the topic deeply enough to respond + +### Product Interest Signals + +Definition: + +- behavior that suggests demand for a deeper paid asset + +Examples: + +- "Do you have a more complete checklist?" +- "Can you share the SOP?" +- "Can you help me review this deployment?" +- repeated requests for the same missing step + +### Paid Conversions + +Definition: + +- actual paid purchases tied to the paid asset path + +## What Counts As Proof To Move Forward + +Do not use one vanity spike as proof. + +For a topic cluster to justify deeper SOP pushes, look for repeated signals such as: + +- multiple articles produce checklist unlocks +- checklist unlocks turn into confirmed subscribers +- confirmed subscribers generate replies or deeper questions +- the same missing step is asked about more than once +- readers ask for a fuller or more executable version + +## What Does Not Count As Proof + +- raw impressions without action +- compliments without follow-up behavior +- traffic with no CTA click +- checklist unlocks with no confirmation and no replies +- personal excitement about a topic + +## First-Pass Funnel To Measure Now + +For the current checklist loop, track this path: + +1. content page view +2. click to checklist page +3. checklist form submit / unlock +4. confirmed subscription +5. welcome email sent +6. welcome email click when available +7. reply / deeper interest signal +8. later SOP interest + +This is enough to make better decisions even before a full analytics stack exists. + +## Collection Method + +### Phase 1: Manual Or Semi-Manual Is Acceptable + +Right now, do not block progress on perfect instrumentation. + +Acceptable phase-1 sources: + +- site analytics page views +- click counts from simple event tracking or link tracking +- Buttondown confirmed subscriber counts by tag +- inbox replies +- manual notes from real conversations + +### Phase 2: Add Better Event Tracking Later + +When the system is stable, improve: + +- CTA click events +- form submit / unlock events +- confirmed subscriber attribution +- SOP interest events + +## Recommended File Format + +Start with one simple file in-repo: + +- `docs/topic-ledger.csv` + +Recommended starter columns: + +```csv +date_published,topic_cluster,content_title,content_type,canonical_url,primary_cta,asset_target,page_views,cta_clicks,asset_unlocks_or_downloads,confirmed_subscribers,replies_or_feedback,product_interest_signals,paid_conversions,notes +``` + +If a CSV feels too rigid later, add: + +- `docs/topic-ledger.md` + +for commentary and interpretation. + +## Initial Rows To Add First + +When the ledger is first created, seed at least: + +1. the homepage checklist CTA +2. the checklist landing page +3. `部署一个 GitHub 项目前,最应该先确认的 10 件事` +4. the checklist success / confirmation page + +Then add Batch 1 article #2 when published. + +## Review Cadence + +### Weekly + +Check: + +- which topic got views +- which topic got CTA clicks +- whether checklist unlocks happened +- whether confirmed subscribers moved + +### Monthly + +Check: + +- which topics created real downstream value +- whether the cluster is producing repeated product-interest signals +- whether the paid SOP path should be pushed harder + +## Decision Rules + +### Keep investing in a topic when: + +- it produces meaningful CTA clicks +- it produces checklist unlocks +- it produces confirmed subscribers +- it produces replies or deeper questions + +### Rewrite or demote a topic when: + +- it gets views but no CTA clicks +- it gets clicks but no unlocks +- it gets unlocks but no confirmations or no follow-up behavior + +### Consider pushing the paid SOP harder when: + +- more than one article in the cluster produces downstream proof +- the same operational pain repeats in replies +- readers ask for a fuller execution version + +## Current Priority + +Do not overbuild the ledger before using it. + +The correct next move after this spec is: + +1. create the first ledger file +2. seed the existing pages and content +3. publish Batch 1 content with explicit CTA mapping +4. review weekly From b96fbc47424fc4d2320151699a5bff2c4cf74c10 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:18:23 +0800 Subject: [PATCH 19/27] Document InsForge reevaluation conditions --- AGENTS.md | 1 + docs/Roadmap.md | 2 ++ docs/ShopPaymentArchitecture.md | 38 +++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 3a295f23b..bca98f1b9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,7 @@ - `/Users/frank_zhang/Library/Mobile Documents/com~apple~CloudDocs/Obsidian 库/5.知识库/07个人成长/08财务自由之路/1当前财务自由系统的项目分工与顺序(2026-03-31).md` - When work touches monetization order, project prioritization, `fzhang.dev`, asset funnels, paid SOPs/templates, bootstrap services, or possible `paperclip` integration, consult the references above before making strategic changes. - When work touches `shop.fzhang.dev`, payment processors, subscriptions, refunds, billing, entitlement sync, or order mirrors, consult `docs/ShopPaymentArchitecture.md` first. +- `InsForge` should not be introduced by default. Re-evaluate it only if `shop.fzhang.dev` later needs a real internal backend for entitlements, order mirrors, admin operations, and repeated backend iteration after payment integration is already stable. - Current cross-project operating model: - `cash flow survival layer + asset compounding layer + product optionality layer` - `MoneyPrinterV2` is the current main execution repo for the asset-compounding layer. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index e917dce4d..d95521f9b 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -41,6 +41,7 @@ Current gap summary: - affiliate-safe comparison / recommendation clusters are not defined yet - welcome email, unsubscribe visibility, tagging, and low-frequency topic sends still need final verification - `shop.fzhang.dev` payment architecture is now decided in principle, but not yet implemented in code +- `InsForge` is intentionally deferred unless the shop backend becomes a real bottleneck after payment integration ## North Star @@ -157,6 +158,7 @@ Current payment architecture rule: - `shop.fzhang.dev` should use a payment / billing platform plus internal order mirror model - do not use `Payoneer receiving account` as the primary checkout solution - current preferred direction is `Paddle` first, `Lemon Squeezy` second, `Stripe` later if deeper control becomes necessary +- re-evaluate `InsForge` only after payment integration and first paid-asset traction make backend coordination the bottleneck ## Phase 6: Site Integration diff --git a/docs/ShopPaymentArchitecture.md b/docs/ShopPaymentArchitecture.md index 65f605eac..f42ac4c74 100644 --- a/docs/ShopPaymentArchitecture.md +++ b/docs/ShopPaymentArchitecture.md @@ -238,6 +238,44 @@ 3. 再补 subscriptions / portal / cancellation flows 4. 最后再考虑更复杂的自定义后台或 billing abstraction +## InsForge Re-Evaluation Condition + +Current judgment: + +- do not introduce `InsForge` now + +Why: + +- the current bottleneck is not backend infrastructure +- the near-term priority is still: + - prove the asset loop + - validate paid digital assets + - choose and integrate a payment platform +- adding a new agent-native backend now would likely increase coordination cost before it creates real leverage + +Re-evaluate `InsForge` only when most of the following become true: + +- `shop.fzhang.dev` needs a real internal backend beyond static pages and payment-hosted flows +- you already have a chosen payment platform and stable webhook model +- you need a persistent internal system for: + - user accounts + - entitlement state + - order / subscription mirrors + - admin operations + - support lookup +- you expect repeated backend changes where an agent-friendly backend stack would save meaningful time +- the first paid asset is already selling or the shop backend has become an active execution bottleneck + +Do not re-evaluate `InsForge` merely because: + +- it looks promising +- it could maybe speed up future backend work +- it feels more modern than the current stack + +One-sentence rule: + +> Only reconsider `InsForge` after payment integration and the first paid asset path are real enough that backend coordination becomes the bottleneck. + ## 这条决策对当前系统的影响 它意味着: From 7b7f4e9f5e948e8830b8384d350474253d0ca0c4 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:33:59 +0800 Subject: [PATCH 20/27] Note GEO repo as future reference --- AGENTS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index bca98f1b9..5b204b09f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,8 @@ - `docs/FinancialFreedomPath.md` - `docs/FzhangHomepageCopy.md` - `docs/ShopPaymentArchitecture.md` +- When work touches agent-facing site structure, AEO / GEO, AI citation visibility, or how `fzhang.dev` / `shop.fzhang.dev` should be optimized for agents and LLM discovery, also consult the upstream `GEO` repo at: + - `/Users/frank_zhang/Documents/文稿 - Frank's MacBook Air/Github项目/GEO` ## Cross-Project Financial Freedom Context - This repo should be evaluated as one lane inside Frank's broader financial-freedom system, not in isolation. From 509c26935a961dd881bed82de8b3a505a8d3e928 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Fri, 3 Apr 2026 13:51:28 +0800 Subject: [PATCH 21/27] Add initial topic ledger and measurement seed --- docs/Roadmap.md | 1 + docs/TopicLedgerMeasurementSpec.md | 9 +++++++-- docs/topic-ledger.csv | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 docs/topic-ledger.csv diff --git a/docs/Roadmap.md b/docs/Roadmap.md index d95521f9b..9182f2a08 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -189,6 +189,7 @@ Direction note: Execution note: - first-pass measurement spec: `docs/TopicLedgerMeasurementSpec.md` +- seeded ledger file: `docs/topic-ledger.csv` ## Decision Filters diff --git a/docs/TopicLedgerMeasurementSpec.md b/docs/TopicLedgerMeasurementSpec.md index 4826e737c..7e13f3d52 100644 --- a/docs/TopicLedgerMeasurementSpec.md +++ b/docs/TopicLedgerMeasurementSpec.md @@ -303,6 +303,11 @@ When the ledger is first created, seed at least: Then add Batch 1 article #2 when published. +Current status: + +- initial ledger file has now been seeded at `docs/topic-ledger.csv` +- next work should update it with real numbers instead of creating a second tracking format + ## Review Cadence ### Weekly @@ -349,7 +354,7 @@ Do not overbuild the ledger before using it. The correct next move after this spec is: -1. create the first ledger file -2. seed the existing pages and content +1. keep `docs/topic-ledger.csv` as the single source of truth for the current funnel +2. update the seeded rows with real numbers 3. publish Batch 1 content with explicit CTA mapping 4. review weekly diff --git a/docs/topic-ledger.csv b/docs/topic-ledger.csv new file mode 100644 index 000000000..a3004b237 --- /dev/null +++ b/docs/topic-ledger.csv @@ -0,0 +1,6 @@ +date_published,topic_cluster,content_title,content_type,status,canonical_url,primary_problem,search_intent_level,primary_cta,asset_target,next_step,page_views,cta_clicks,asset_unlocks_or_downloads,confirmed_subscribers,welcome_email_opens,welcome_email_clicks,replies_or_feedback,product_interest_signals,paid_conversions,proof_summary,what_worked,what_failed,next_iteration,notes +,deployment,Homepage checklist CTA,resource_page,published,https://www.fzhang.dev/,"Make the site immediately point readers toward a reusable execution asset instead of leaving them in general blog navigation.",medium,领取免费清单,deployment-checklist,Click through to checklist page,,,,,,,,,,,Seed row for homepage-to-checklist path,Use as entry point baseline +,deployment,开源 AI 项目部署前检查清单,resource_page,published,https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/,"Convert deployment-intent readers into checklist unlocks and confirmed subscribers.",high,领取免费清单,deployment-checklist,Unlock checklist and confirm subscription,,,,,,,,,,,Primary capture page for current funnel, +,deployment,Checklist success / confirmation page,success_page,published,https://www.fzhang.dev/checklist-sent/,"Bridge resource unlock intent into confirmation, welcome flow, and later low-frequency topic emails.",medium,下载 Markdown 版清单,deployment-checklist,Confirm subscription or continue reading,,,,,,,,,,,Track post-submit dropoff and confirmation behavior, +2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster, +,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Batch 1 article #2 draft target, From 97709afdd5b5b0dbd70aee7f2574caa3076c2c07 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:15:22 +0800 Subject: [PATCH 22/27] Add second deployment article draft --- .../Article_LocalRunsButServerBreaks.md | 223 ++++++++++++++++++ docs/assets/FirstContentBatchExecutionPlan.md | 4 + docs/topic-ledger.csv | 2 +- 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 docs/assets/Article_LocalRunsButServerBreaks.md diff --git a/docs/assets/Article_LocalRunsButServerBreaks.md b/docs/assets/Article_LocalRunsButServerBreaks.md new file mode 100644 index 000000000..0aaa1b0ed --- /dev/null +++ b/docs/assets/Article_LocalRunsButServerBreaks.md @@ -0,0 +1,223 @@ +# 第二篇文章:为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? + +## 标题 + +为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? + +## 摘要 + +很多开源 AI / Web 项目真正拖垮人的地方,不是在第一次本地跑起来,而是在你准备把它搬到服务器、域名、反代和真实用户场景里时,才发现一连串之前没暴露出来的问题。这篇文章要讲清楚:为什么“本地能跑”几乎从来不等于“可以上线”,以及你在真正部署前应该先确认什么。 + +## 正文 + +很多人第一次看到一个开源 AI 项目时,往往会经历一个很相似的过程: + +- 先看 README +- 拉代码 +- 跑通本地依赖 +- 看到页面能打开 +- 然后立刻产生一种感觉: + +> 好像差不多已经成了。 + +问题就出在这句“差不多”。 + +很多项目真正把人拖死的,不是在本地起不来,而是在你已经以为它“基本没问题”之后,一放到服务器上才开始连续暴露问题。 + +所以,如果你也有过下面这种体验: + +- 本地明明能跑 +- 一换机器就报错 +- 一上服务器就开始出各种奇怪问题 +- 你以为只是“环境差异”,结果最后发现根本不是一两个小坑 + +那这篇文章想讲的,就是这件事背后的结构。 + +## 1. “本地能跑”证明的是代码有机会活着,不是项目已经能上线 + +本地跑通最多只能证明几件事: + +- 代码在你的机器上暂时没有立刻死掉 +- 你手头这套依赖刚好能配合它 +- 你本地的默认环境刚好没有卡死它 + +但它完全不保证: + +- 换台机器还能跑 +- 换到服务器还能跑 +- 有真实用户访问时还能跑 +- 上线后出了问题你知道怎么恢复 + +这两者之间差的不是“最后一步部署命令”。 + +差的是一整层现实条件: + +- 环境 +- 网络 +- 进程 +- 数据 +- 权限 +- 暴露面 +- 恢复能力 + +所以,“本地能跑”不是终点,它只是第一轮筛选。 + +## 2. 本地环境里有很多“服务器上不会替你兜底”的条件 + +你在本地能跑,往往是因为你的机器默默替你提供了很多隐藏条件。 + +比如: + +- 你已经装好了某些依赖 +- 某个端口没有冲突 +- 你当前 shell 里刚好带着环境变量 +- 本地文件路径刚好和文档写的一样 +- 你自己电脑上的权限足够宽松 + +这些东西在服务器上经常全部消失。 + +结果就是: + +- 本地 `npm install` 没问题,服务器上构建报错 +- 本地图片上传正常,服务器上权限不对 +- 本地 API 能调通,服务器上出站网络或鉴权失败 +- 本地 SQLite 跑得动,服务器上并发或持久化立刻变成问题 + +很多人把这种落差理解成: + +> 服务器环境真烦。 + +但更准确的说法是: + +> 本地环境太会替你掩盖问题。 + +## 3. 你本地验证的,可能根本不是“真实主路径” + +还有一种非常常见的错觉是: + +- 页面打开了 +- 按钮能点 +- 某个 demo 流程跑了一遍 + +于是你默认: + +> 核心流程没问题。 + +但真正上线会暴露的是你没认真走过的那部分: + +- 登录态切换 +- 第三方回调 +- 文件上传 +- 后台任务 +- 邮件发送 +- 鉴权 +- 存储 +- Webhook + +也就是说,你本地验证的,可能只是“能打开 UI”,不是“真实业务主路径可用”。 + +如果一个项目真正要上线,至少要回答: + +- 最关键的 1 到 2 条主路径是什么? +- 这些路径我有没有在更接近真实环境的地方走通? + +如果没有,那“本地能跑”几乎没法给你真正的上线信心。 + +## 4. 数据和状态,一旦离开本地就不再是小问题 + +本地调试时,你很容易忽略数据问题,因为本地数据坏了,大不了删掉重来。 + +但一旦项目进入更真实的环境,数据问题就开始变重: + +- 数据到底落本地文件、数据库还是对象存储? +- 日志存在哪? +- 上传文件会不会丢? +- 你现在能不能说清楚怎么备份一次? +- 如果你今天配错了,怎么回滚? + +这也是很多项目为什么在“本地没问题”之后,一上服务器就开始混乱。 + +因为你突然从“代码是否能跑”切换成了“状态是否能维护”。 + +而后者才是真正的部署问题。 + +## 5. 公网暴露以后,问题不再只是“能不能用”,而是“敢不敢开” + +很多项目本地调试时,默认所有东西都很自然: + +- 调试页面开着 +- 默认账号没改 +- 报错信息很完整 +- 某些后台路径没鉴权 + +本地这么做不一定马上出事。 + +但一旦你准备加域名、反代、HTTPS,或者让别人访问,问题就变了: + +- 哪些端点绝对不能公开? +- 哪些后台路径只能自己看? +- 哪些调试入口要关? +- 哪些日志或报错会直接暴露内部结构? + +很多人说自己“部署失败”,其实不是应用挂了,而是到了这一步突然意识到: + +> 我根本还没准备好让这个东西真的见人。 + +## 6. 真正拖垮人的不是技术点本身,而是顺序错了 + +还有一个更深的原因是:很多人并不是不会解决问题,而是解决顺序完全乱了。 + +常见的混乱顺序是: + +- 先改 UI +- 再接额外能力 +- 然后才补环境变量 +- 再之后才想鉴权 +- 最后上线前才第一次认真看日志、备份和回滚 + +这会导致项目看上去一直在动,但其实越来越不可控。 + +更稳的顺序通常应该是: + +1. 先确认项目是否适合当前场景 +2. 再梳理环境与依赖 +3. 再验证主路径 +4. 再确认数据与状态 +5. 再收敛明显风险 +6. 最后才进入公网暴露和正式上线 + +很多项目不是死在“技术太难”,而是死在“顺序太乱”。 + +## 7. 所以真正该问的不是“为什么服务器这么多坑” + +更好的问题是: + +> 我是不是把一个只在本地暂时活着的东西,误判成了已经接近可上线的项目? + +一旦你这样问,很多问题就会变得更清楚: + +- 哪些问题是本地环境掩盖的? +- 哪些主路径我根本还没验证? +- 哪些风险现在必须处理,哪些可以后补? +- 我到底是在“部署”,还是只是在“继续盲试”? + +## 最后 + +如果你现在手上的开源 AI 项目处在这种状态: + +- 本地能跑 +- 但你不敢说它真的能上线 +- 你知道后面还有很多问题,但不知道先抓哪一个 + +那你现在最需要的,可能不是继续往服务器上硬推,而是先把部署前该确认的结构理顺。 + +我把这类最容易在“本地能跑”之后才暴露出来的问题,整理进了一份: + +**《开源 AI 项目部署前检查清单》** + +如果你想在真正部署前,先把顺序、风险和必须先确认的点看清楚,可以先从这份清单开始。 + +## 文末 CTA + +- `领取免费清单` +- `查看相关文章` diff --git a/docs/assets/FirstContentBatchExecutionPlan.md b/docs/assets/FirstContentBatchExecutionPlan.md index 86c261560..559ef4bc5 100644 --- a/docs/assets/FirstContentBatchExecutionPlan.md +++ b/docs/assets/FirstContentBatchExecutionPlan.md @@ -49,6 +49,10 @@ ### 2. 为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题? +当前状态: + +- 已有文章草稿 + 角色: - 问题放大型文章 diff --git a/docs/topic-ledger.csv b/docs/topic-ledger.csv index a3004b237..0feaca89e 100644 --- a/docs/topic-ledger.csv +++ b/docs/topic-ledger.csv @@ -3,4 +3,4 @@ date_published,topic_cluster,content_title,content_type,status,canonical_url,pri ,deployment,开源 AI 项目部署前检查清单,resource_page,published,https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/,"Convert deployment-intent readers into checklist unlocks and confirmed subscribers.",high,领取免费清单,deployment-checklist,Unlock checklist and confirm subscription,,,,,,,,,,,Primary capture page for current funnel, ,deployment,Checklist success / confirmation page,success_page,published,https://www.fzhang.dev/checklist-sent/,"Bridge resource unlock intent into confirmation, welcome flow, and later low-frequency topic emails.",medium,下载 Markdown 版清单,deployment-checklist,Confirm subscription or continue reading,,,,,,,,,,,Track post-submit dropoff and confirmation behavior, 2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster, -,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Batch 1 article #2 draft target, +,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_LocalRunsButServerBreaks.md, From aabf4677938caa4479fc8955940548600245a5c5 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:29:22 +0800 Subject: [PATCH 23/27] Add distribution validation plan and content tracking --- docs/DistributionValidationPlan.md | 253 ++++++++++++++++++ docs/Roadmap.md | 10 + docs/assets/FirstContentBatchExecutionPlan.md | 11 + docs/distribution-log.csv | 3 + docs/topic-ledger.csv | 1 + 5 files changed, 278 insertions(+) create mode 100644 docs/DistributionValidationPlan.md create mode 100644 docs/distribution-log.csv diff --git a/docs/DistributionValidationPlan.md b/docs/DistributionValidationPlan.md new file mode 100644 index 000000000..aae90799a --- /dev/null +++ b/docs/DistributionValidationPlan.md @@ -0,0 +1,253 @@ +# 最小分发验证计划 + +这份文档的目标不是做完整增长战略。 + +目标是: + +- 用最低成本验证当前 deployment cluster 的问题到底更偏向内容,还是更偏向分发 +- 给 `fzhang.dev` 一个可以执行、可以复盘、可以进入 ledger 的最小分发动作集 +- 在不依赖广告投放和重运营的情况下,先建立第一批真实分发样本 + +## 为什么现在要做这件事 + +当前网站的问题,不适合直接判断为: + +- 内容不够吸引人 + +也不适合直接判断为: + +- 只是没人知道 + +更准确的说法是: + +- 当前样本量太小,无法区分内容问题和分发问题 + +所以现在要做的不是继续猜,而是设计一套: + +- 样本足够小 +- 成本足够低 +- 可以重复 +- 可以记录结果 + +的分发验证计划。 + +## 本轮验证的目标 + +只验证 deployment cluster,不扩到全站所有主题。 + +本轮验证重点观察: + +1. 有人看到内容吗? +2. 看到的人会点 checklist 吗? +3. 点了的人会 unlock / confirm 吗? +4. 有没有人回复或问更深的问题? + +## 本轮验证资产 + +使用下面这些资产: + +- `部署一个 GitHub 项目前,最应该先确认的 10 件事` +- `为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` +- `开源 AI 项目部署前检查清单` + +## 分发原则 + +### 做的事 + +- 只做与内容高度相关的分发 +- 只做低成本、可复用、可记录的动作 +- 优先找“已经有问题的人”,而不是广撒网 + +### 不做的事 + +- 不做泛流量买量 +- 不做与主题无关的硬广 +- 不做每天高频维护的社媒矩阵 +- 不因为缺流量就立刻怀疑内容质量 + +## 最小分发渠道 + +### 1. GitHub 相关场景 + +适合内容: + +- 部署 +- README 判断 +- self-hosting +- launch readiness + +动作: + +- 找与你文章主题高度相关的仓库 +- 只在真正合适的场景里参与: + - issue + - discussion + - README feedback + - self-hosting / deployment 讨论 +- 如果文章刚好能帮助解决问题,就自然贴出相关文章或 checklist + +记录方式: + +- 渠道:`github` +- 具体位置:仓库 / issue / discussion URL +- 内容类型:文章 or checklist + +### 2. 个人知识网络 / 现有收藏渠道 + +动作: + +- 从你已整理的知识库和项目收藏里,挑出已经保存过的高相关分发渠道 +- 本轮只激活 2 到 3 个,不要一次开太多 + +记录方式: + +- 渠道名 +- 发的是什么资产 +- 是否有点击 / 回复 + +### 3. 轻量社交验证 + +动作: + +- 不是做大规模社媒运营 +- 只把文章核心观点压缩成 1 条简短内容 +- 链回文章,不直接硬卖 checklist + +使用条件: + +- 该平台上有你现成账号 +- 发一条的成本足够低 + +记录方式: + +- 渠道:`x` / `linkedin` / 其他 +- 链接到哪篇文章 +- 是否带来点击 + +### 4. 已有订阅者 / 已有关系链 + +动作: + +- 如果 deployment 主题有真正值得发的新内容 +- 可以做一次低频、轻量、相关的提醒 + +原则: + +- 不是群发轰炸 +- 只发和当前 cluster 高度相关的更新 + +## 本轮执行节奏 + +### Week 1 + +- 发布或整理好本轮核心文章 +- 只做 3 到 5 个分发动作 +- 每个动作都记录 + +### Week 2 + +- 看哪些动作带来: + - 页面访问 + - checklist 点击 + - unlock / confirm +- 不急着扩大渠道 + +### Week 3 + +- 保留有效动作 +- 删除无反馈动作 +- 补 1 篇新的 cluster 内容 + +### Week 4 + +- 总结: + - 是没人看到 + - 还是看到了不点 + - 还是点了但不确认 + +## 如何判断是“内容问题”还是“分发问题” + +### 更像分发问题 + +如果出现: + +- 页面访问本身很低 +- checklist 页访问也低 +- 没有足够样本支撑判断 + +那先归因为: + +- 分发样本不足 + +### 更像内容 / 承接问题 + +如果出现: + +- 页面访问开始有了 +- 但 CTA 点击低 +- 或 checklist 页访问有了,但 unlock / confirm 很低 + +那才更像: + +- 内容表达问题 +- CTA 问题 +- landing page / resource page 承接问题 + +### 更像主题本身问题 + +如果出现: + +- 有曝光 +- 有点击 +- 但几乎没有后续 deeper interest + +那说明: + +- 这个主题可能有阅读价值 +- 但不一定有足够强的产品或订阅承接力 + +## 本轮最少需要记录什么 + +每次分发动作至少记: + +- `date` +- `channel` +- `asset` +- `destination_url` +- `reason_this_channel_fits` +- `result_after_3_to_7_days` + +建议追加到: + +- `docs/distribution-log.csv` + +推荐列: + +```csv +date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_days,notes +``` + +## 本轮成功标准 + +不是立刻大量涨粉。 + +本轮成功的标准是: + +- 我们能开始分辨: + - 分发问题 + - 内容问题 + - 承接问题 + +只要你能回答下面这些问题,本轮就算成功: + +1. 哪种渠道至少能带来一些目标流量? +2. 哪篇内容更容易带来 checklist 点击? +3. 点击后是哪里开始流失? +4. 有没有出现值得继续加深 SOP 路径的真实问题? + +## 当前下一步 + +1. 先为 deployment cluster 做第一轮 3 到 5 个分发动作 +2. 用 `topic-ledger.csv` 记录资产层结果 +3. 用 `distribution-log.csv` 记录渠道层结果 +4. 一周后再判断问题更偏内容还是分发 diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 9182f2a08..1a77ec8ac 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -33,6 +33,7 @@ The following work is already represented in committed docs or repo changes: - the first content batch and paid SOP path now have execution specs in `docs/assets/` - a cross-project execution summary now exists in `docs/FinancialFreedomExecutionStack.md` - a first-pass topic ledger / measurement spec now exists in `docs/TopicLedgerMeasurementSpec.md` +- a minimum distribution validation plan now exists in `docs/DistributionValidationPlan.md` Current gap summary: @@ -42,6 +43,7 @@ Current gap summary: - welcome email, unsubscribe visibility, tagging, and low-frequency topic sends still need final verification - `shop.fzhang.dev` payment architecture is now decided in principle, but not yet implemented in code - `InsForge` is intentionally deferred unless the shop backend becomes a real bottleneck after payment integration +- distribution validation has a plan, but still needs real channel actions and logged results ## North Star @@ -190,6 +192,14 @@ Execution note: - first-pass measurement spec: `docs/TopicLedgerMeasurementSpec.md` - seeded ledger file: `docs/topic-ledger.csv` +- seeded distribution log: `docs/distribution-log.csv` + +## Phase 8: Distribution Validation + +- [x] Define a minimum distribution validation plan for the deployment cluster +- [ ] Execute the first 3 to 5 real distribution actions +- [ ] Log channel-level results in `docs/distribution-log.csv` +- [ ] Distinguish whether the current bottleneck is traffic, CTA click-through, or capture conversion ## Decision Filters diff --git a/docs/assets/FirstContentBatchExecutionPlan.md b/docs/assets/FirstContentBatchExecutionPlan.md index 559ef4bc5..90bd54170 100644 --- a/docs/assets/FirstContentBatchExecutionPlan.md +++ b/docs/assets/FirstContentBatchExecutionPlan.md @@ -170,3 +170,14 @@ - 同类问题反复出现 如果这些信号不出现,就先继续优化主题与漏斗,不急着扩 product lane。 + +## Distribution Validation + +Current rule: + +- do not assume low subscriber count automatically means weak content +- first build a minimum distribution sample before making that judgment + +Execution reference: + +- `docs/DistributionValidationPlan.md` diff --git a/docs/distribution-log.csv b/docs/distribution-log.csv new file mode 100644 index 000000000..2260af121 --- /dev/null +++ b/docs/distribution-log.csv @@ -0,0 +1,3 @@ +date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_days,notes +2026-04-07,seed,部署一个 GitHub 项目前,最应该先确认的 10 件事,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Seed row for future manual distribution tracking. Use this format for real channel tests.",pending,No real distribution action logged yet +2026-04-07,seed,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,TBD,"Seed row for future manual distribution tracking after publish.",pending,Draft exists but no real distribution action logged yet diff --git a/docs/topic-ledger.csv b/docs/topic-ledger.csv index 0feaca89e..0770eb67f 100644 --- a/docs/topic-ledger.csv +++ b/docs/topic-ledger.csv @@ -4,3 +4,4 @@ date_published,topic_cluster,content_title,content_type,status,canonical_url,pri ,deployment,Checklist success / confirmation page,success_page,published,https://www.fzhang.dev/checklist-sent/,"Bridge resource unlock intent into confirmation, welcome flow, and later low-frequency topic emails.",medium,下载 Markdown 版清单,deployment-checklist,Confirm subscription or continue reading,,,,,,,,,,,Track post-submit dropoff and confirmation behavior, 2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster, ,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_LocalRunsButServerBreaks.md, +,deployment,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,article,draft,,"Bridge deployment-intent readers from checklist thinking into SOP-level prioritization and risk sequencing.",high,先领清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Next Batch 1 bridge article target, From 14f9f860646f6c6258261e9bf56ffb6951fc275c Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:32:49 +0800 Subject: [PATCH 24/27] Add third deployment article and promotion prompts --- docs/FzhangGitHubPromotionExecutionPrompt.md | 161 +++++++++++++ docs/FzhangObsidianPromotionStrategyPrompt.md | 142 +++++++++++ docs/assets/Article_RisksMustHandleFirst.md | 227 ++++++++++++++++++ docs/assets/FirstContentBatchExecutionPlan.md | 4 + docs/distribution-log.csv | 1 + docs/topic-ledger.csv | 2 +- 6 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 docs/FzhangGitHubPromotionExecutionPrompt.md create mode 100644 docs/FzhangObsidianPromotionStrategyPrompt.md create mode 100644 docs/assets/Article_RisksMustHandleFirst.md diff --git a/docs/FzhangGitHubPromotionExecutionPrompt.md b/docs/FzhangGitHubPromotionExecutionPrompt.md new file mode 100644 index 000000000..8362c61b5 --- /dev/null +++ b/docs/FzhangGitHubPromotionExecutionPrompt.md @@ -0,0 +1,161 @@ +# 给 GitHub 工作区 AI 的 `fzhang.dev` 推广执行提示词 + +你现在位于我的 GitHub 项目工作区,请基于当前仓库里的真实文档、草稿和路线图,为 `fzhang.dev` 制定一套**执行层的推广方案**。 + +你的任务不是再讲一遍抽象增长理论,而是: + +1. 读取当前项目内已经固定下来的策略与漏斗文档 +2. 根据这些文档,产出一套未来 4 周可执行的推广与分发方案 +3. 尽量把结果固化为仓库内可复用的文档、台账、模板或执行清单 + +--- + +## 你必须先读取的文件 + +请先检查并吸收以下文件: + +- `AGENTS.md` +- `docs/Roadmap.md` +- `docs/FinancialFreedomExecutionStack.md` +- `docs/DistributionValidationPlan.md` +- `docs/TopicLedgerMeasurementSpec.md` +- `docs/topic-ledger.csv` +- `docs/distribution-log.csv` +- `docs/assets/FirstContentBatchExecutionPlan.md` +- `docs/assets/Article_DeployGitHubProject10Checks.md` +- `docs/assets/Article_LocalRunsButServerBreaks.md` +- `docs/assets/Article_RisksMustHandleFirst.md` + +如有必要,也可以参考: + +- 上级目录中的 `GEO` 仓库,判断是否有值得吸收的 AEO / GEO 执行方式 + +--- + +## 你必须理解的当前业务约束 + +当前站点不是传统 agency 站点。 + +当前角色分工是: + +- `MoneyPrinterV2`:内容资产与漏斗素材生产 +- `fzhang.dev`:内容站、信任面、长尾流量入口、资源领取与邮件订阅入口 +- `shop.fzhang.dev`:后续数字产品成交面,当前不是第一开发重点 + +当前最重要的漏斗是: + +1. 部署 / launch readiness 相关文章 +2. 免费资源:`开源 AI 项目部署前检查清单` +3. 邮件确认、welcome、低频 topic updates +4. 后续付费 `上线与基础加固 SOP` + +当前真实问题不是已经确定“内容不行”。 + +更准确的说法是: + +- 当前样本量太小,无法区分问题到底主要出在内容、分发,还是资源页承接 + +所以你要帮助我做的是: + +- 低成本建立第一批真实分发样本 +- 用行动而不是猜测去判断瓶颈 +- 让已有内容资产开始获得真实访问、点击、订阅和反馈 + +必须遵守的约束: + +- 不依赖广告投放 +- 不做高频重运营矩阵 +- 适合单人执行 +- 优先低成本、可复用、可记录的分发动作 +- 不要把项目带回“卖更多人工服务”的方向 + +--- + +## 你的任务 + +### 任务 1:基于现有资产,判断最适合先推广什么 + +请你先基于现有文章、清单和后续 SOP 路径,回答: + +- 哪 1 到 2 篇文章最适合先拿去做真实分发验证? +- 清单页应该在推广中扮演什么角色? +- 第三篇桥接文应该何时加入分发,而不是只停留在草稿? + +### 任务 2:给出未来 4 周的最小可执行推广计划 + +请输出一个非常具体的 4 周执行方案。 + +至少包含: + +- 每周要做哪些最小动作 +- 每个动作对应哪个渠道 +- 每个渠道为什么适合当前 deployment cluster +- 每个动作链接到哪篇文章或哪一页资源 +- 每周最少需要记录哪些结果 + +### 任务 3:给出“首批真实分发动作”清单 + +不要给泛泛渠道建议。 + +请尽量产出这种级别的结果: + +- GitHub 场景里该找哪类仓库 / issue / discussion +- 哪些现有关系链或低成本平台值得先试 +- 哪些平台只适合轻量验证,而不值得重投入 +- 每类渠道分别适合投放文章、清单页,还是短摘要 + +### 任务 4:给出可直接复用的分发素材模板 + +请尽量产出可直接执行的模板,例如: + +- GitHub discussion / comment 的自然表达模板 +- X / LinkedIn 的短帖模板 +- 面向已有订阅者的低频更新模板 +- 文章摘要如何压缩成“问题 -> 观点 -> 链接”的短分发格式 + +这些模板要与当前站点定位一致: + +- 技术内容优先 +- 判断力优先 +- 不硬卖 +- 以帮助真实有问题的人为前提 + +### 任务 5:如果合适,请直接更新仓库内文档 + +如果你判断下面这些文档需要更新,请直接修改: + +- `docs/DistributionValidationPlan.md` +- `docs/distribution-log.csv` +- `docs/topic-ledger.csv` +- `docs/assets/FirstContentBatchExecutionPlan.md` + +如果你新增文档,请优先放在 `docs/` 下,并让命名清晰、可复用。 + +--- + +## 输出要求 + +请按下面结构输出: + +1. 当前最适合优先推广的资产 +2. 未来 4 周执行计划 +3. 首批 3 到 5 个真实分发动作 +4. 可复用的分发模板 +5. 需要更新或新增的仓库文档 +6. 一个压缩后的执行 shortlist(只保留现在最该做的 3 件事) + +--- + +## 额外要求 + +- 不要默认用付费广告 +- 不要把重点放在服务销售 +- 不要输出只有团队才能执行的重运营方案 +- 如果你认为某些文档里的执行顺序需要微调,请明确说明依据 +- 如果你发现当前仓库缺少某个关键执行文档,可以直接补 + +你的目标不是“想出更多增长点子”,而是让当前这条: + +`长尾文章 -> 免费清单 -> 邮件确认 / welcome -> 后续 SOP` + +开始真正获得第一批可复盘的真实样本。 diff --git a/docs/FzhangObsidianPromotionStrategyPrompt.md b/docs/FzhangObsidianPromotionStrategyPrompt.md new file mode 100644 index 000000000..3d672514c --- /dev/null +++ b/docs/FzhangObsidianPromotionStrategyPrompt.md @@ -0,0 +1,142 @@ +# 给 Obsidian 知识库 AI 的 `fzhang.dev` 推广策略提示词 + +你现在要基于我的 Obsidian 知识库,帮我为 `fzhang.dev` 制定一套**方法论层的站点推广策略**。 + +请不要给泛泛的“多发社媒、多做 SEO”建议。 + +你的任务是: + +1. 先从知识库中提取我已经保存过的推广方法、渠道线索、个人品牌思路、内容分发方式、AEO / GEO / SEO 经验、开发者社区玩法 +2. 再把这些零散资料整合成一套适合我当前阶段的推广方法论 +3. 最终服务于一个明确目标:**让 `fzhang.dev` 获得更多高相关访问量、更多清单领取、更多订阅确认,并为后续付费 SOP / 模板验证提供样本** + +--- + +## 你必须先理解的当前业务背景 + +当前我不是在做一个传统 agency 官网,也不是在做“先卖服务”的站。 + +当前系统角色是: + +- `MoneyPrinterV2` = 内容资产与可转化素材的生产仓库 +- `fzhang.dev` = 信任面、长尾流量入口、邮件订阅与资源领取入口 +- `shop.fzhang.dev` = 以后承接付费数字产品的收款与解锁,不是当前第一优先级 + +当前第一条资产路径是: + +1. 长尾文章 +2. 免费资源:`开源 AI 项目部署前检查清单` +3. 邮件确认 / welcome / 低频主题更新 +4. 以后再承接 `上线与基础加固 SOP`、模板、低接触产品 + +当前要推广的核心主题簇不是泛 AI,而是更聚焦的: + +- 开源 AI 项目部署 +- launch readiness +- self-hosting / public launch risk +- 上线顺序、基础加固、环境与暴露面判断 + +当前需要遵守的约束: + +- 不依赖广告投放 +- 不做高频、重运营社媒矩阵 +- 要适合单人长期执行 +- 要偏内容资产复利,而不是短期流量刺激 +- 不能把站点重新带回“卖更多人工服务”的方向 + +--- + +## 你的任务 + +### 任务 1:先从知识库里提取可用素材 + +请优先检索并整合这些类型的笔记或资料: + +- 网站推广 / 独立站增长 +- SEO / AEO / GEO / AI 引用优化 +- 内容分发 / repurposing / 一稿多发 +- GitHub、Reddit、Hacker News、X、LinkedIn、知乎、微信公众号、开发者社区等渠道方法 +- 个人品牌 / OPC / 知识资产增长 +- newsletter / owned audience / lead magnet / 免费资源增长 +- 开发者内容营销、技术内容分发、问题驱动型内容 + +不要只列标题。 + +你要提炼每类资料里真正对当前阶段有用的原则。 + +### 任务 2:判断哪些推广方式最适合我现在 + +请围绕这个问题做判断: + +> 对一个内容优先、单人执行、以“技术长尾内容 -> 免费清单 -> 邮件订阅 -> 后续 SOP” 为主路径的网站来说,未来 3 个月最值得优先采用的推广方式是什么? + +请你不要默认“全渠道都要做”。 + +你要筛出: + +- 最适合我的 3 个主渠道 +- 可以作为补充的 2 个次渠道 +- 当前明确不值得投入的渠道 + +并解释为什么。 + +### 任务 3:构造一套“方法论层”的推广框架 + +请你输出一套适合当前阶段的推广框架,至少包含: + +1. 核心推广原则 +2. 渠道选择逻辑 +3. 内容选题与分发如何配合 +4. 一篇长文如何拆成多个分发素材 +5. 如何兼顾 SEO / GEO / 社交分发 / owned audience +6. 如何避免高维护成本 + +### 任务 4:给出未来 8 到 12 周的建议节奏 + +请你不要做成重运营排班表。 + +而是给我一套“单人可持续执行”的节奏,比如: + +- 每周应该固定做哪些事 +- 每篇文章发布后,应该做哪几步最小分发动作 +- 什么时候该继续扩内容,什么时候该先补承接页或 CTA +- 什么时候该认为问题更像“分发不足”,什么时候更像“内容不够吸引” + +### 任务 5:给出判断标准和 measurement 建议 + +请明确回答: + +- 在当前阶段,我应该优先看哪些信号来判断推广是否有效? +- 如何区分: + - 没人看到 + - 看到了但不点 + - 点了但不订阅 + - 订阅了但没有后续兴趣 + +请尽量让这些判断标准贴近单人站点,而不是企业级团队指标。 + +--- + +## 输出要求 + +请按下面结构输出: + +1. 从知识库中提炼出的可用推广原则 +2. 当前阶段最适合我的 3 个主渠道 + 2 个次渠道 +3. 一套内容驱动、低维护、可复利的推广框架 +4. 未来 8 到 12 周的执行节奏 +5. 判断“内容问题 vs 分发问题 vs 承接问题”的标准 +6. 一个压缩后的执行 shortlist(只保留最该先做的 3 件事) + +--- + +## 额外要求 + +- 不要给需要大预算的方案 +- 不要默认投广告 +- 不要把重心放在“先卖服务” +- 不要输出只适合团队执行的重运营体系 +- 要尽量引用知识库中已有资料的思路,而不是凭空发明 +- 如果知识库里有互相冲突的方法,请帮我判断当前阶段该选哪一种 + +如果你认为某些知识库资料虽然看起来有道理,但不适合我当前阶段,也请明确指出来。 diff --git a/docs/assets/Article_RisksMustHandleFirst.md b/docs/assets/Article_RisksMustHandleFirst.md new file mode 100644 index 000000000..a6899c7af --- /dev/null +++ b/docs/assets/Article_RisksMustHandleFirst.md @@ -0,0 +1,227 @@ +# 第三篇文章:开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? + +## 标题 + +开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? + +## 摘要 + +很多人做开源 AI / Web 项目部署时,不是败在问题太多,而是败在顺序太乱:该先处理的没先处理,可以后补的却花了很多时间。这篇文章要讲清楚,为什么“风险排序”比“问题清单越长越好”更重要,以及第一次准备上线时,哪些事情真的该先收住,哪些可以留到后面迭代。 + +## 正文 + +很多项目不是没有问题。 + +而是问题太多,所以人很容易一上来就陷入两种极端: + +- 要么想一次把所有问题都解决 +- 要么干脆先不分轻重,哪里冒出来就先修哪里 + +结果通常都不太好。 + +前一种会让你永远觉得“还不能上线”。 +后一种会让你看起来一直在忙,但项目越来越乱。 + +所以真正有用的问题不是: + +> 这个项目有哪些风险? + +而是: + +> 这些风险里,哪些必须在上线前先处理,哪些可以在第一版跑稳以后再补? + +这两个问题看起来很像,但结果完全不一样。 + +## 1. 不是所有问题,都配得上“上线前必须解决” + +很多人一旦准备把项目搬上服务器,就会同时想到一大堆事情: + +- UI 还不够顺手 +- 日志系统不够漂亮 +- 邮件通知还没接 +- 管理后台还没做细 +- 缓存策略还没优化 +- 权限体系想重构一下 +- 还想顺手换个框架 + +这些事里,当然有些以后都值得做。 + +但如果你在第一版上线前,把它们都当成同一优先级,项目就很容易被拖进“永远准备中”的状态。 + +更稳的思路应该是先区分三类问题: + +1. 不先处理,上线后大概率会直接出事 +2. 不先处理,虽然不会立刻出事,但会明显影响第一版可用性 +3. 不先处理也没关系,只是后面体验会更差或效率更低 + +真正要先抓的,是第一类。 + +## 2. 第一类:会让你“根本不该公开上线”的风险,必须先处理 + +这类问题的共同特点是: + +- 它不是体验问题 +- 它不是“以后再优化”的问题 +- 它会直接决定你现在到底能不能把这个东西见人 + +典型例子包括: + +- 公开暴露的页面或接口没有鉴权 +- 默认账号、默认密码、调试入口还开着 +- 环境变量和密钥管理是混乱的 +- 你根本说不清哪些路径适合公网,哪些不适合 + +如果这些问题还没想清楚,就算页面已经能打开,也不应该把它理解成“差不多可以上线”。 + +很多所谓的部署失败,并不是程序真的挂了,而是到了准备公开暴露那一步,你才发现: + +> 这个东西目前只是能启动,不是真的敢开。 + +## 3. 第二类:会让核心主路径不稳定的风险,也必须先处理 + +有些问题虽然不直接等于安全事故,但会让你的第一版根本不稳。 + +比如: + +- 最关键的 1 到 2 条主路径你还没真正走通 +- 本地能跑,但换到服务器就不稳定 +- 文件上传、第三方 API、后台任务、Webhook 这些真实动作没有验证 +- 一旦报错,你根本不知道问题会卡在哪一层 + +这类问题为什么要先处理? + +因为第一版上线,不需要“所有功能都完美”。 +但至少要做到: + +- 关键路径能跑 +- 关键路径出问题时你能定位 +- 关键路径挂了以后你知道该怎么恢复 + +如果连这三点都还做不到,那你现在最缺的不是“继续加功能”,而是“先把主路径跑稳”。 + +## 4. 第三类:和数据、状态、恢复相关的风险,优先级通常也很高 + +很多人对“上线风险”的理解,容易只停留在: + +- 页面能不能打开 +- 接口能不能返回 + +但真正把人拖垮的,经常是状态问题: + +- 数据到底存在哪 +- 上传文件会不会丢 +- 改错配置以后怎么回滚 +- 数据坏了以后怎么恢复 +- 哪些日志至少要保留,方便排查 + +这些事情不一定要求你第一天就做得很完整。 + +但上线前至少要有一个“最小答案”: + +- 数据落点我知道 +- 最基本的备份方式我知道 +- 关键配置改坏了以后,我知道怎么退回上一版 + +如果这些答案一个都没有,那风险就不只是“第一版粗糙”,而是“第一版一出问题就很难收回来”。 + +## 5. 那哪些问题通常可以后补? + +下面这些内容,通常更适合放到第一版跑稳以后再补: + +- 更细的 UI 打磨 +- 非核心流程的体验优化 +- 更完整的监控面板 +- 更复杂的权限颗粒度 +- 更漂亮的日志可视化 +- 为了“以后也许会用到”而提前做的大重构 + +这不是说它们不重要。 + +而是说,在项目还没证明: + +- 这个方向值得继续 +- 这条主路径真的会被用 +- 这套部署方式真的能跑稳 + +之前,把大量时间放在这些事情上,往往回报不高。 + +很多项目不是因为基础不够强而拖慢,而是因为太早进入“精装修模式”。 + +## 6. 一个简单判断法:这件事不做,会导致哪种后果? + +如果你现在拿不准某个问题该不该先处理,可以先问四个问题: + +### 问题 1:不做它,会不会让我现在根本不该公开上线? + +如果会,那优先级很高。 + +### 问题 2:不做它,核心主路径会不会明显不稳定? + +如果会,那也应优先处理。 + +### 问题 3:不做它,一旦出问题我是不是几乎没有恢复手段? + +如果是,这件事也不该拖太后。 + +### 问题 4:不做它,影响的到底是“能不能跑”,还是“跑得还不够好”? + +如果只是后者,大概率可以后补。 + +很多顺序判断,靠的不是技术复杂度,而是这个问题对应的后果级别。 + +## 7. 更稳的上线顺序,通常长这样 + +如果今天要从零准备上线一个开源 AI 项目,我会更倾向于按这个顺序走: + +1. 先判断项目是否真的适合当前场景 +2. 先划清本地、内网、公网的边界 +3. 先收住明显暴露面和鉴权问题 +4. 先跑通最关键的 1 到 2 条主路径 +5. 先确认数据、配置和最小恢复方案 +6. 再去补体验、自动化、监控和各种优化 + +这个顺序的核心不是“做得保守”。 + +而是先解决: + +- 会不会出大问题 +- 会不会根本不稳 +- 出问题以后有没有办法收回来 + +等这些最基础的东西站住了,后面的优化才真正有意义。 + +## 最后 + +很多人真正卡住,不是因为不会部署,而是因为没有把“必须先做”和“可以后补”分开。 + +于是最后会出现两种结果: + +- 该先处理的没处理,项目很快暴露出结构性问题 +- 可以后补的先做了一大堆,时间和精力被提前耗掉 + +如果你现在手上也有一个准备上线的开源 AI 项目,但你还不确定: + +- 哪些风险该先处理 +- 哪些问题可以以后再补 +- 第一版到底应该先收住什么 + +那你现在最需要的,通常不是继续把问题越列越长,而是先把顺序理清楚。 + +我把这类最容易在上线前混在一起的问题,整理进了一份: + +**《开源 AI 项目部署前检查清单》** + +如果你想先把部署前该确认的关键点过一遍,可以先从这份清单开始。 + +如果你更关心的是: + +- 第一版上线顺序怎么排 +- 基础加固应该做到什么程度 +- 哪些问题该先处理,哪些可以后补 + +我也在继续整理更完整的上线与基础加固 SOP。 + +## 文末 CTA + +- `先领清单` +- `如果你更关心上线与基础加固,留意后续 SOP` diff --git a/docs/assets/FirstContentBatchExecutionPlan.md b/docs/assets/FirstContentBatchExecutionPlan.md index 90bd54170..8abc5b048 100644 --- a/docs/assets/FirstContentBatchExecutionPlan.md +++ b/docs/assets/FirstContentBatchExecutionPlan.md @@ -73,6 +73,10 @@ ### 3. 开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补? +当前状态: + +- 已有文章草稿:`docs/assets/Article_RisksMustHandleFirst.md` + 角色: - checklist 到 SOP 的桥梁文 diff --git a/docs/distribution-log.csv b/docs/distribution-log.csv index 2260af121..225a4894c 100644 --- a/docs/distribution-log.csv +++ b/docs/distribution-log.csv @@ -1,3 +1,4 @@ date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_days,notes 2026-04-07,seed,部署一个 GitHub 项目前,最应该先确认的 10 件事,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Seed row for future manual distribution tracking. Use this format for real channel tests.",pending,No real distribution action logged yet 2026-04-07,seed,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,TBD,"Seed row for future manual distribution tracking after publish.",pending,Draft exists but no real distribution action logged yet +2026-04-07,seed,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,TBD,"Seed row for future manual distribution tracking after publish.",pending,Draft exists at docs/assets/Article_RisksMustHandleFirst.md but no real distribution action logged yet diff --git a/docs/topic-ledger.csv b/docs/topic-ledger.csv index 0770eb67f..7b49b200c 100644 --- a/docs/topic-ledger.csv +++ b/docs/topic-ledger.csv @@ -4,4 +4,4 @@ date_published,topic_cluster,content_title,content_type,status,canonical_url,pri ,deployment,Checklist success / confirmation page,success_page,published,https://www.fzhang.dev/checklist-sent/,"Bridge resource unlock intent into confirmation, welcome flow, and later low-frequency topic emails.",medium,下载 Markdown 版清单,deployment-checklist,Confirm subscription or continue reading,,,,,,,,,,,Track post-submit dropoff and confirmation behavior, 2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster, ,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_LocalRunsButServerBreaks.md, -,deployment,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,article,draft,,"Bridge deployment-intent readers from checklist thinking into SOP-level prioritization and risk sequencing.",high,先领清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Next Batch 1 bridge article target, +,deployment,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,article,draft,,"Bridge deployment-intent readers from checklist thinking into SOP-level prioritization and risk sequencing.",high,先领清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_RisksMustHandleFirst.md, From a14c57281134e50360f35be993c66297bd5428a0 Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:36:33 +0800 Subject: [PATCH 25/27] Update distribution validation asset scope --- docs/DistributionValidationPlan.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/DistributionValidationPlan.md b/docs/DistributionValidationPlan.md index aae90799a..3e5c5834d 100644 --- a/docs/DistributionValidationPlan.md +++ b/docs/DistributionValidationPlan.md @@ -48,8 +48,14 @@ - `部署一个 GitHub 项目前,最应该先确认的 10 件事` - `为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` +- `开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?` - `开源 AI 项目部署前检查清单` +说明: + +- 第三篇桥接文当前仍是 draft,更适合作为本轮后半段或发布后立即进入分发验证的资产 +- 当前最先验证的仍应是首发文章与问题放大型文章,不必一开始三篇同时推进 + ## 分发原则 ### 做的事 From 48c01fcc0b9ae6cab705eaf65a8f6e4a28afc64f Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:05:47 +0800 Subject: [PATCH 26/27] Add traffic strategy and distribution execution docs --- docs/DistributionExecutionKit.md | 379 ++++++++++++++++ docs/DistributionValidationPlan.md | 168 +++++++- docs/FzhangTrafficStrategy.md | 406 ++++++++++++++++++ docs/Roadmap.md | 8 +- docs/assets/FirstContentBatchExecutionPlan.md | 25 ++ docs/distribution-log.csv | 8 +- docs/topic-ledger.csv | 9 +- 7 files changed, 986 insertions(+), 17 deletions(-) create mode 100644 docs/DistributionExecutionKit.md create mode 100644 docs/FzhangTrafficStrategy.md diff --git a/docs/DistributionExecutionKit.md b/docs/DistributionExecutionKit.md new file mode 100644 index 000000000..0bc113ce5 --- /dev/null +++ b/docs/DistributionExecutionKit.md @@ -0,0 +1,379 @@ +# Deployment Cluster 分发执行包 + +这份文档把当前 deployment cluster 的分发动作,固化成一个单人可执行、可记录、可复用的执行包。 + +目标不是做大而全的增长体系。 + +目标是: + +- 让第一批真实分发动作可以立刻开跑 +- 让每个动作都能回到 `distribution-log.csv` +- 让文章、checklist、邮件和后续 SOP 之间的关系更清楚 + +## 1. 当前最适合优先推广的资产 + +### P1:`部署一个 GitHub 项目前,最应该先确认的 10 件事` + +为什么优先: + +- 搜索意图最明确 +- 最适合 GitHub / self-hosting / README 语境 +- 最容易把“解释版”导向 checklist “执行版” + +最适合的渠道: + +- GitHub discussion +- GitHub issue comment +- 已有关系链里的定向转发 +- 低频订阅更新 + +### P1:`为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` + +为什么优先: + +- 问题感更强 +- 更适合被压缩成短帖或评论 +- 更容易在社媒和 GitHub 对话里触发共鸣 + +最适合的渠道: + +- X +- LinkedIn +- GitHub 回复 +- 与有部署经验的朋友私下转发 + +### P2:`开源 AI 项目部署前检查清单` + +正确角色: + +- 承接页 +- 执行资源 +- 判断 CTA 与资源页承接是否成立的关键节点 + +不建议默认直接冷启动推广 checklist,除非: + +- 对方明确要 checklist +- 对方已在私聊或邮件里提出明确问题 +- 你已经通过文章建立了上下文 + +### P2:`开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?` + +加入条件: + +- 已完成第一轮 3 到 5 个真实分发动作 +- 已出现更深一层的风险排序 / hardening 问题 +- 或文章 1 / 2 已经开始带来 checklist 点击,需要桥接到 SOP + +## 2. 未来 4 周执行计划 + +### Week 1:建立第一批真实样本 + +目标: + +- 不再停留在“文档已准备好” +- 让文章 1 / 2 真正进入外部场景 + +最小动作: + +1. 检查文章 1、文章 2、checklist 页链接与 CTA 是否顺畅 +2. 做 2 个 GitHub 场景回复 +3. 做 1 条 X 或 LinkedIn 短帖 + +渠道与链接: + +- GitHub discussion / issue -> 文章 1 或文章 2 +- X / LinkedIn -> 文章 2 优先 + +最少记录: + +- 动作发在哪 +- 用的是哪篇文章 +- 3 到 7 天后是否带来点击或反馈 + +### Week 2:补足样本,但不扩太广 + +目标: + +- 在已有渠道里补样本 +- 初步判断“看不到”还是“看到不点” + +最小动作: + +1. 再做 1 个 GitHub 回复 +2. 给已有关系链或已有订阅者发 1 次低频更新 +3. 再发 1 条短帖,复用 Week 1 表达方式 + +渠道与链接: + +- GitHub -> 文章 1 +- 关系链 / Email -> checklist 或文章 1 +- X / LinkedIn -> 文章 2 + +最少记录: + +- 页面访问是否开始出现 +- checklist 点击是否出现 +- 是否有人回复更深问题 + +### Week 3:只放大有效动作,决定桥接文是否上场 + +目标: + +- 看是否有必要引入文章 3 +- 避免把分发面铺得太散 + +最小动作: + +1. 保留前两周最有效的 2 个动作类型 +2. 若出现更深问题,发布并分发文章 3 +3. 若没有更深问题,继续放大文章 1 / 2 + +渠道与链接: + +- GitHub -> 文章 1 / 文章 3 +- Email / 关系链 -> 文章 3(仅在桥接信号出现时) + +最少记录: + +- 文章 3 是否带来更强的 SOP 兴趣 +- 是否有人问“有更完整版本吗” + +### Week 4:验证可复制性,不只看一次偶然反馈 + +目标: + +- 重复胜出动作 +- 用第二次结果判断是否可复制 + +最小动作: + +1. 重复 2 个前期最有效动作 +2. 汇总 4 周数据 +3. 判断瓶颈属于: + - 分发不足 + - 文章到 checklist 的点击不足 + - checklist / confirm 承接不足 + +最少记录: + +- 哪个渠道动作最容易带来目标流量 +- 哪篇文章最容易带来 checklist 点击 +- 是否已经出现 SOP 兴趣信号 + +## 3. 首批 5 个真实分发动作 + +### 动作 1:GitHub discussion 里的“是否值得部署 / 怎么部署更稳” + +找什么: + +- 有 active discussion 的开源 AI / self-hosted / developer tool 仓库 +- 讨论内容涉及: + - self-hosting + - deployment + - production readiness + - `is this ready for production` + +适合投什么: + +- 首选文章 1 + +不适合: + +- 纯功能讨论 +- 无关的 bug thread +- 与部署无关的 feature request + +### 动作 2:GitHub issue / discussion 里的“本地能跑,服务器挂了” + +找什么: + +- 安装问题、环境差异、server-only bug +- README 与真实部署差异引发的 thread + +适合投什么: + +- 首选文章 2 + +价值: + +- 这是最接近文章 2 标题的问题现场 +- 不是硬投放,而是对真实问题的结构化回答 + +### 动作 3:已有关系链里的定向转发 + +找什么人: + +- 最近在折腾自托管 / 上线 / VPS / Docker 的朋友 +- 之前问过你部署问题的人 +- 保存过类似仓库或内容的人 + +适合投什么: + +- 如果对方问题还泛:文章 1 +- 如果对方已经在执行:checklist + +价值: + +- 更容易获得第一批真实反馈 +- 适合低成本验证“资源承接是否成立” + +### 动作 4:X 上的短帖验证 + +适合投什么: + +- 文章 2 优先 + +原因: + +- “本地能跑 != 可上线”很适合一句话切入 +- 技术圈对这种踩坑型判断更容易停留 + +不值得当前重投入的原因: + +- 需要持续互动才会放大 +- 当前更适合做轻量验证,不适合做日更矩阵 + +### 动作 5:给已有订阅者发一次低频 deployment update + +适合投什么: + +- 文章 1 + checklist +- 后续如出现桥接信号,再换文章 3 + +为什么值得: + +- 这是当前最接近 owned audience 的现成流量 +- 可以帮助判断“已有信任关系的人”会不会点 checklist + +## 4. 哪些平台只适合轻量验证 + +下面这些平台当前只适合轻量验证,不值得重投入: + +- X +- LinkedIn +- 泛技术群聊 +- 泛社区转帖平台 + +原因: + +- 需要高频运营才能放大 +- 当前样本目标是“先有真实样本”,不是“做账号增长” +- 更高杠杆的地方仍然是 GitHub 场景与已有关系链 + +## 5. 可复用分发模板 + +### 模板 A:GitHub discussion / comment + +适用: + +- 对方已经在问部署、上线、自托管或 production readiness + +模板: + +```text +这个问题我最近正好系统整理过一次。 + +如果你现在还在判断“这个项目值不值得正式部署”,我建议先别急着上服务器,先把这几件事想清楚: + +1. 它到底适合本地、内网,还是公网 +2. README 里的环境和你真实环境差多少 +3. 哪些页面 / 端点其实不该直接暴露 + +我把这类判断整理成了一篇短文,偏 deployment readiness,不是教条式教程: +{文章链接} + +如果你更想直接按步骤过一遍,我还整理了一份 checklist: +{checklist 链接,可选} +``` + +使用规则: + +- 默认先给文章 +- 只有当对方明确要 checklist 或已经进入执行阶段时,再补 checklist + +### 模板 B:X / LinkedIn 短帖 + +适用: + +- 分发文章 2 + +模板: + +```text +很多开源 AI 项目真正拖垮人的地方,不是“本地跑不起来”。 + +而是你以为它已经差不多能上线了, +结果一上服务器才发现: + +- 环境不一样 +- 关键路径没验证 +- 暴露面没想清楚 +- 回滚方案也没有 + +“本地能跑”通常只说明它在你的机器上暂时活着。 +不等于它真的 ready for deployment。 + +我把这件事写成了一篇短文: +{文章链接} +``` + +### 模板 C:低频订阅者更新 + +适用: + +- 已有订阅者 +- 低频 topic update + +模板: + +```text +主题:这周整理了一篇更实用的 deployment 文章 + +这周我把一个很常见、但很容易被误判的问题整理成了文章: + +《{文章标题}》 + +核心不是“怎么把项目先跑起来”, +而是先判断它到底是否真的适合进入部署 / 公网暴露阶段。 + +如果你最近也在折腾开源 AI 项目上线,可能会有帮助: +{文章链接} + +如果你更想直接按执行顺序过一遍,也可以直接拿这份清单: +{checklist 链接} +``` + +### 模板 D:问题 -> 观点 -> 链接 + +适用: + +- 任意短分发动作 + +模板: + +```text +问题: +为什么很多项目本地能跑,但一上线就开始出问题? + +观点: +因为“本地能跑”验证的是代码是否暂时活着, +不是它是否已经具备 deployment readiness。 + +链接: +{文章链接} +``` + +## 6. 每周最少要记录什么 + +每周至少记录: + +- 做了哪些动作 +- 每个动作指向哪个资产 +- 哪个动作开始带来目标访问 +- 哪篇文章开始带来 checklist 点击 +- 有没有出现更深的回复 / 问题 + +记录位置: + +- 渠道动作:`docs/distribution-log.csv` +- 资产表现:`docs/topic-ledger.csv` diff --git a/docs/DistributionValidationPlan.md b/docs/DistributionValidationPlan.md index 3e5c5834d..e61fe3651 100644 --- a/docs/DistributionValidationPlan.md +++ b/docs/DistributionValidationPlan.md @@ -56,6 +56,72 @@ - 第三篇桥接文当前仍是 draft,更适合作为本轮后半段或发布后立即进入分发验证的资产 - 当前最先验证的仍应是首发文章与问题放大型文章,不必一开始三篇同时推进 +## 当前优先推广顺序 + +### 第一优先:`部署一个 GitHub 项目前,最应该先确认的 10 件事` + +原因: + +- 最接近当前最明确的部署搜索意图 +- 最容易作为 GitHub / self-hosting / launch readiness 讨论里的自然回答 +- 最容易把“先判断是否值得部署”导向 checklist + +适合承担: + +- 第一轮真实分发验证的主入口文 +- GitHub discussion / issue comment / 轻量社媒短帖的主链接目标 + +### 第二优先:`为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?` + +原因: + +- 问题感更强,适合社媒、转发和对话式分发 +- 能把“本地跑通”与“真实可上线”之间的差异讲透 +- 更容易让读者意识到自己还没准备好,进而点击 checklist + +适合承担: + +- 第二个真实分发验证入口 +- X / LinkedIn / GitHub 回复中的“问题放大”入口 + +### Checklist 在推广中的角色 + +`开源 AI 项目部署前检查清单` 不应该承担冷启动分发主入口角色。 + +更合适的角色是: + +- 作为文章里的“执行版下一步” +- 作为对高意图读者的资源承接页 +- 作为判断瓶颈是在点击前还是点击后的关键观察点 + +默认顺序应是: + +- 先分发文章 +- 再让文章把读者导向 checklist + +例外情况: + +- 对方明确在问“有没有现成 checklist / checklist 模板 / 上线前 checklist” +- 已经在私聊、邮件或较强关系链里,适合直接给资源页 + +### 第三篇桥接文何时加入 + +`开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?` 不应只是停留在草稿,但也不应该抢在第一轮样本前面。 + +更合适的加入时点: + +- 第一轮已经完成 3 到 5 个真实分发动作之后 +- 且开始出现下面任一信号: + - 有人点击 checklist,但没有进一步确认 + - 有人问“到底先处理哪些问题” + - 文章 1 / 2 已经能带来一定目标访问,需要一篇更靠近 SOP 的桥接文 + +它的职责不是“带来第一批陌生流量”,而是: + +- 承接更深的风险排序问题 +- 测试读者会不会继续向 SOP 方向移动 +- 为后续付费资产建立更自然的认知阶梯 + ## 分发原则 ### 做的事 @@ -146,30 +212,106 @@ ### Week 1 -- 发布或整理好本轮核心文章 -- 只做 3 到 5 个分发动作 -- 每个动作都记录 +- 确保文章 1 与文章 2 都处于可分发状态 +- 检查 checklist 页、确认页、welcome 路径是否能承接 +- 执行 3 个最低成本动作: + - 2 个 GitHub 高相关场景 + - 1 个轻量社交或已有关系链动作 +- 每个动作都写入 `docs/distribution-log.csv` ### Week 2 +- 补 2 到 3 个动作,但只保留和 deployment cluster 高度相关的场景 +- 至少覆盖: + - 1 个 GitHub discussion / issue + - 1 个 X 或 LinkedIn 短帖 + - 1 个已有订阅者或已有关系链更新 - 看哪些动作带来: - 页面访问 - checklist 点击 - unlock / confirm -- 不急着扩大渠道 +- 不急着扩大平台数量,只增加样本密度 ### Week 3 -- 保留有效动作 -- 删除无反馈动作 -- 补 1 篇新的 cluster 内容 +- 只保留有效动作类型 +- 删除完全无反馈的动作类型 +- 如果前两周已经出现目标访问或 checklist 点击,补上第三篇桥接文 +- 如果样本仍很弱,继续放大文章 1 / 2 的分发,不急着把桥接文推到前台 ### Week 4 +- 复用前 3 周中最有效的 1 到 2 个动作模式 +- 做 2 个“重复动作”,验证是否可复制 - 总结: - 是没人看到 - 还是看到了不点 - 还是点了但不确认 + - 第三篇桥接文是否值得升为常规分发资产 + +## 4 周最小动作矩阵 + +| 周次 | 最小动作 | 渠道 | 指向资产 | 为什么适合当前 cluster | +| --- | --- | --- | --- | --- | +| Week 1 | 回答 2 个 GitHub 上真实 deployment / self-hosting / launch readiness 问题 | GitHub discussion / issue | 文章 1 或文章 2 | 这些场景本来就存在真实问题,最接近“有问题的人” | +| Week 1 | 发 1 条“问题 -> 观点 -> 链接”短帖 | X 或 LinkedIn | 文章 2 优先 | “本地能跑 != 可上线”更适合短帖切入 | +| Week 2 | 再做 1 个 GitHub 回复 + 1 个关系链发送 | GitHub + 私信 / 邮件 / 收藏网络 | 文章 1 或 checklist | 一个找公开问题,一个找低成本定向流量 | +| Week 2 | 给已有订阅者发 1 次低频 update | Email | 文章 1 + checklist | 订阅者已接受技术内容,不需要硬卖 | +| Week 3 | 视样本决定是否发布并分发文章 3 | GitHub / X / Email | 文章 3 | 只在桥接需求出现时启动,避免过早分散注意力 | +| Week 4 | 重复前 2 个最有效动作 | 与前期胜出渠道一致 | 优胜资产 | 用重复验证“可复制性”,而不是只看一次偶然反馈 | + +## 渠道与资产匹配规则 + +### GitHub discussion / issue comment + +优先投放: + +- 文章 1 +- 文章 2 + +只在下面场景自然放链接: + +- 对方在问是否适合部署某个项目 +- 对方在问为什么服务器环境出问题 +- 对方在问 self-hosting / launch readiness / public exposure 相关问题 + +### 关系链 / 私聊 / 收藏网络 + +优先投放: + +- checklist +- 文章 1 + +适合原因: + +- 对方已经认识你或已经看过你类似内容 +- 直接发资源的心理成本低 +- 更容易拿到真实反馈而不是纯曝光 + +### X / LinkedIn + +优先投放: + +- 文章 2 +- 文章 1 + +适合原因: + +- 适合用一句强问题感的钩子切入 +- 适合把长文压缩成“问题 -> 判断 -> 链接” +- 适合轻量验证,不适合当前阶段重投入 + +### 订阅者更新 + +优先投放: + +- 文章 1 + checklist +- 文章 3(仅在桥接信号出现后) + +适合原因: + +- 当前目标不是高频 newsletter,而是低频 topic updates +- 可用来验证“已有信任读者”会不会往 checklist 或更深资产走 ## 如何判断是“内容问题”还是“分发问题” @@ -233,6 +375,13 @@ date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_days,notes ``` +实际执行时建议把 `notes` 写得更具体,例如: + +- 目标仓库 / 目标 discussion 类型 +- 使用了哪种模板 +- 是文章链接还是 checklist 链接 +- 是否需要 3 天后回看 + ## 本轮成功标准 不是立刻大量涨粉。 @@ -257,3 +406,8 @@ date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_ 2. 用 `topic-ledger.csv` 记录资产层结果 3. 用 `distribution-log.csv` 记录渠道层结果 4. 一周后再判断问题更偏内容还是分发 + +## 执行参考 + +- 4 周动作与模板:`docs/DistributionExecutionKit.md` +- 第一批内容顺序:`docs/assets/FirstContentBatchExecutionPlan.md` diff --git a/docs/FzhangTrafficStrategy.md b/docs/FzhangTrafficStrategy.md new file mode 100644 index 000000000..7ec044185 --- /dev/null +++ b/docs/FzhangTrafficStrategy.md @@ -0,0 +1,406 @@ +# `fzhang.dev` 流量与分发策略 + +这份文档固化当前阶段对 `fzhang.dev` 的流量、分发与转化判断。 + +它不负责记录每一次具体动作。 + +它负责回答三件事: + +1. 当前最值得相信的推广原则是什么 +2. 当前 3 个月最值得优先投入哪些渠道 +3. 如何判断问题出在分发、内容,还是承接 + +对应关系: + +- 方法论与渠道判断:本文件 +- 4 周执行动作与模板:`docs/DistributionExecutionKit.md` +- 分发验证逻辑:`docs/DistributionValidationPlan.md` +- 具体渠道动作记录:`docs/distribution-log.csv` +- 资产层结果记录:`docs/topic-ledger.csv` + +## 1. 当前阶段的总判断 + +当前 `fzhang.dev` 不应被当成: + +- 强销售型独立站 +- 高频社媒矩阵的承接页 +- 先靠服务转化的网站 + +当前更适合被当成: + +- content-first 的信任面 +- long-tail 问题入口 +- 免费资源领取与邮件订阅入口 +- 后续 SOP / 模板验证的前置层 + +当前主路径是: + +1. 长尾问题文章 +2. 免费资源:`开源 AI 项目部署前检查清单` +3. 邮件确认 / welcome / 低频主题更新 +4. 后续 `上线与基础加固 SOP` + +## 2. 可复用推广原则 + +### 资产优先,不做重销售站 + +当前优先级不是把 `fzhang.dev` 变成更强的 service homepage。 + +当前优先级是: + +- 先积累可复用内容资产 +- 先把注意力转成自有受众 +- 再让后续 SOP / 模板有验证基础 + +### 内容不是目的,内容是可转化素材 + +每篇内容都不该只承担“被阅读”这一个任务。 + +它至少应该同时服务于: + +- 流量获取 +- 判断力展示 +- 免费资源承接 +- 后续 SOP 验证 + +### 当前起手应是 lead-magnet-first,不是 newsletter-first + +当前最合理的起手顺序不是“先做一份 newsletter 再慢慢想发什么”。 + +更合理的是: + +- 先用高意图文章承接问题 +- 再用具体 lead magnet 完成第一次转化 +- 后续再用邮件把一次访问变成持续触达 + +### 网站是大本营,外部平台只是前哨站 + +内容应优先完整地沉淀在 `fzhang.dev`。 + +外部平台更适合承担: + +- 把问题投向真实现场 +- 触发点击 +- 引导回站 + +而不是承担“主内容资产”的长期存储角色。 + +### AEO / GEO 的核心是答案化、结构化、作者化 + +当前要争取的不只是搜索点击,还包括 AI 引用与答案抽取。 + +所以内容层应持续强调: + +- 结论先行 +- 问题式标题 +- 列表、表格、FAQ、判断块 +- 作者信息、更新时间、结构化站点信号 + +### 分发要问题驱动,不要链接驱动 + +当前最适合你的分发方式不是“把链接发出去”。 + +而是: + +- 去真实问题现场回答 +- 用文章里的判断结构化回答问题 +- 只在确实合适时再自然附上原文或资源 + +### 分发杠杆不等于主题价值 + +`social-auto-upload`、公众号同步、社媒转发这些动作,只能放大已经值得分发的资产。 + +它们不能替代下面这些证据: + +- 阅读 +- checklist 点击 +- checklist 提交 +- 订阅确认 +- 回复 +- 是否有人追问更深版本 + +## 3. 当前 3 个主渠道 + +### 主渠道 1:`fzhang.dev` 的 SEO + AEO + GEO + +这是最符合当前约束的主渠道: + +- 低维护 +- 可复利 +- 与当前漏斗天然一致 + +最适合承接的主题: + +- 部署前判断 +- launch readiness +- 基础加固 +- self-hosting / public launch risk +- 上线后故障与暴露面 + +### 主渠道 2:问题型开发者社区 + +当前最适合的不是“做账号矩阵”,而是去真实问题场景答题。 + +优先顺序建议: + +- 中文:V2EX、知乎 +- 英文:Reddit、Stack Overflow + +这类渠道适合你,因为: + +- 意图强 +- 问题具体 +- 文章能自然作为延伸阅读 +- 更容易带来“有问题的人”而不是泛流量 + +### 主渠道 3:站内清单 + 邮件确认链路 + +它严格说不是曝光渠道,但在当前阶段必须按主渠道经营。 + +因为你真正需要的不是浏览量本身,而是: + +- 清单领取 +- 邮件确认 +- welcome 触达 +- 后续 SOP 验证样本 + +如果这条链路没跑稳,前端分发越多,浪费越大。 + +## 4. 当前 2 个次渠道 + +### 次渠道 1:微信公众号 + +适合做: + +- 低频同步 +- 摘要版导流 +- 对站内文章的二次分发 + +不适合再当成: + +- 当前主阵地 +- 主要变现渠道 + +### 次渠道 2:GitHub + +GitHub 更适合作为: + +- 高相关信任面 +- 开源语境下的展示层 +- 示例、脚本、README、issue/discussion 的问题现场 + +它很适合 deployment 这个主题簇,但不应被误判成唯一主拉新渠道。 + +## 5. 当前不值得重投入的方向 + +### 高频 X / LinkedIn 运营 + +当前阶段不适合把它们当主战场。 + +原因: + +- 关系网门槛高 +- 链接分发不稳定 +- 需要持续互动 +- 对单人维护成本偏高 + +### Product Hunt / Hacker News 式打榜 + +这更适合短期爆发或广泛反馈,不适合当前目标: + +- 持续高相关流量 +- 清单领取 +- 邮件订阅 +- SOP 需求验证 + +### 付费目录 / 批量外链服务 + +可以作为边角动作,但不应进入主策略。 + +### 全平台矩阵式分发 + +这是典型团队打法,不适合当前的单人约束。 + +### 把寄生平台当增长本体 + +例如 Perplexity Pages 这类平台,可用来观察选题与 GEO 表现,但不应替代 `fzhang.dev` 本体增长。 + +## 6. 低维护、可复利的推广框架 + +### 第一步:先做可被检索的问题答案 + +每篇文章都应优先回答一个真实问题,而不是泛泛表达观点。 + +### 第二步:再接可被领取的资源 + +文章结尾不只停在“看完了”。 + +而应明确给出下一步: + +- 判断表 +- 检查清单 +- 执行版资源 + +### 第三步:最后再接可被付费的 SOP + +只有当下面这些信号开始重复出现时,才说明可以往 SOP 推进: + +- 同类问题反复出现 +- checklist 有稳定点击或提交 +- 有人追问更深版本 + +## 7. 一篇长文的最小拆分法 + +每篇长文最小只拆 4 层,不做复杂矩阵: + +1. 站内原文:权威版 +2. TL;DR:开头答案块 +3. 社区回答版:150-300 字问题回答 +4. 资源 CTA:一句具体的领取理由 + +这已经足够支撑: + +- SEO / GEO +- 社区答题 +- 低频公众号同步 +- checklist 承接 + +## 8. 未来 8 到 12 周的节奏 + +### 第 1-2 周:先把承接闭环跑通 + +重点不是扩散,而是确认下面这条链路真的能工作: + +- 清单页 +- 表单 +- 确认 +- 资源交付 +- welcome +- 基础埋点 + +### 第 3-6 周:连续发布 4 篇可转化长尾文 + +优先围绕当前主题簇: + +- 部署前检查 +- 上线前暴露面判断 +- 自托管何时不该上公网 +- 上线后最常见故障 + +### 第 7-8 周:把最好的一篇升级成 hub + +不急着开新坑。 + +先把表现最好的一篇补成更完整的“终极指南”: + +- FAQ +- 判断表 +- 下载物 +- 内链 + +### 第 9-12 周:开始为 SOP 做样本验证 + +重点不是立刻卖 SOP,而是观察: + +- 哪些问题重复出现 +- 哪些订阅者会回复 +- 哪些文章最容易带来领取 + +## 9. 每周固定动作 + +当前单人节奏建议固定为: + +- 1 次选题 +- 1 次产出 +- 1 次最小分发 +- 1 次复盘 + +更具体地说: + +- 从社区问题、站内问题、AI 问题链里选 1 个题 +- 新写 1 篇,或升级 1 篇旧文 +- 去 2-3 个相关场景回答 +- 看访问、领取、回复是否出现 + +## 10. 如何判断问题出在哪 + +### 没人看到 + +如果: + +- 搜索曝光低 +- AI 不引用 +- 社区回答也没人看 + +那更像: + +- 分发不足 +- 或选题不够贴近真实问题 + +### 看到了但不点 + +如果: + +- 曝光有了 +- CTR 很低 +- 社区内容有人看但不进站 + +那更像: + +- 标题问题 +- 摘要不够尖 +- 问题定义不够准确 + +### 点了但不订阅 + +如果: + +- 文章有阅读 +- checklist 提交少 + +那更像: + +- CTA 太弱 +- lead magnet 命名不够具体 +- 文章意图和资源不匹配 + +### 订阅了但没有后续兴趣 + +如果: + +- 确认率还行 +- welcome 打开 / 点击 / 回复弱 + +那更像: + +- 后续价值承诺不清 +- 用户没看到“为什么还要继续关注你” + +## 11. 当前阶段够用的粗阈值 + +下面这些不是行业标准,而是当前阶段够用的诊断线: + +- 文章曝光起来但 CTR 长期低于约 `2%`:先改标题 / 摘要 +- 文章阅读不错但清单提交低于约 `3-5%`:先改 CTA / 资源命名 +- 提交后确认率低于约 `70%`:先查邮件送达与流程摩擦 +- 确认后 welcome 打开低于约 `40-50%`:先改主题行和第一封价值承诺 + +## 12. 当前压缩后的执行 shortlist + +### 1. 先把清单领取闭环跑通 + +页面、表单、确认、交付、welcome、埋点全部可用。 + +### 2. 先做 1 个 4-6 篇的小主题簇 + +只围绕 deployment / launch readiness / hardening,不扩到泛 AI。 + +### 3. 先建立“每篇文章 3 步分发 SOP” + +当前最小 SOP: + +1. 站内发布 +2. 去 2-3 个问题场景回答 +3. 做 1 次低频同步 / 通知 + +做满 8-12 周后,再决定是否继续扩 GitHub 信任层或推出 SOP 预售页。 diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 1a77ec8ac..126c30ed0 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -34,6 +34,8 @@ The following work is already represented in committed docs or repo changes: - a cross-project execution summary now exists in `docs/FinancialFreedomExecutionStack.md` - a first-pass topic ledger / measurement spec now exists in `docs/TopicLedgerMeasurementSpec.md` - a minimum distribution validation plan now exists in `docs/DistributionValidationPlan.md` +- a first distribution execution kit now exists in `docs/DistributionExecutionKit.md` +- a traffic strategy note now exists in `docs/FzhangTrafficStrategy.md` Current gap summary: @@ -237,9 +239,9 @@ If the answer to 1-3 is "no", it is probably off-strategy. ## Executable Shortlist -1. Upgrade the checklist landing page so visitors immediately understand it is an execution asset, not a gated copy of a public article. -2. Stabilize the first real owned-audience path: confirmation, welcome email, visible subscription management, and low-frequency topic sends. -3. Add first-pass measurement for the checklist funnel: page views, submits, confirmed subscribers, and downstream clicks. +1. Execute the first 3 to 5 real distribution actions for article 1 / article 2 and log them in `docs/distribution-log.csv`. +2. Use the first real sample to distinguish whether the current bottleneck is traffic, article-to-checklist click-through, or checklist / confirmation conversion. +3. Only after the first distribution sample exists, decide whether article 3 should move from bridge draft into regular distribution and SOP-intent testing. ## Portfolio Rule diff --git a/docs/assets/FirstContentBatchExecutionPlan.md b/docs/assets/FirstContentBatchExecutionPlan.md index 8abc5b048..486d8e3be 100644 --- a/docs/assets/FirstContentBatchExecutionPlan.md +++ b/docs/assets/FirstContentBatchExecutionPlan.md @@ -132,6 +132,31 @@ - 再桥接到 SOP - 再往更细执行主题推进 +## 分发顺序微调 + +内容发布顺序仍然保持上面的结构,但分发顺序需要更保守: + +1. 先分发文章 1 +2. 再分发文章 2 +3. 先让文章把目标读者导向 checklist +4. 第三篇桥接文在第一轮分发样本后再加入 + +依据: + +- 当前最缺的是第一批真实分发样本,不是更多内容草稿 +- 文章 1 与文章 2 已经足够覆盖“高意图入口 + 问题放大入口” +- 第三篇桥接文更适合承接已经进入思考和执行阶段的读者,而不是承担冷启动曝光 + +## 第三篇桥接文的启用条件 + +满足下面任一条件,就可以把第三篇加入常规分发: + +- 文章 1 / 2 已开始带来 checklist 点击 +- 出现“哪些风险先处理”的真实问题 +- 有人开始问更完整、更深的版本 + +如果这些信号还没出现,就继续优先放大文章 1 / 2,不急着让桥接文抢主入口。 + ## 每篇内容的最小完成标准 每篇文章发布前都至少满足: diff --git a/docs/distribution-log.csv b/docs/distribution-log.csv index 225a4894c..ee700cc24 100644 --- a/docs/distribution-log.csv +++ b/docs/distribution-log.csv @@ -1,4 +1,6 @@ date,channel,asset,destination_url,reason_this_channel_fits,result_after_3_to_7_days,notes -2026-04-07,seed,部署一个 GitHub 项目前,最应该先确认的 10 件事,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Seed row for future manual distribution tracking. Use this format for real channel tests.",pending,No real distribution action logged yet -2026-04-07,seed,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,TBD,"Seed row for future manual distribution tracking after publish.",pending,Draft exists but no real distribution action logged yet -2026-04-07,seed,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,TBD,"Seed row for future manual distribution tracking after publish.",pending,Draft exists at docs/assets/Article_RisksMustHandleFirst.md but no real distribution action logged yet +2026-04-07,github_discussion,部署一个 GitHub 项目前,最应该先确认的 10 件事,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Active GitHub discussions about self-hosting, deployment readiness, or whether an open-source project is ready to go beyond local testing are the closest match to this article's search and problem intent.",planned,"Planned action: answer 1 real discussion with a short 3-point summary plus article link. Only use when the discussion is clearly about deployment judgment." +2026-04-07,github_issue_comment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,TBD,"Issue threads or setup discussions where maintainers and users are stuck on environment mismatch, server-only failures, or README-to-production gaps are the most natural context for this article.",planned,"Planned action: reply in 1 real issue or discussion after publish. Focus on 'local works, server breaks' scenarios, not generic bugs." +2026-04-07,x_short_post,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,TBD,"This topic has stronger problem amplification and is easier to compress into a short 'problem -> judgment -> link' post without needing a high-frequency posting system.",planned,"Planned action: publish 1 short post after article 2 is live. Keep it technical and non-promotional." +2026-04-07,relationship_chain,开源 AI 项目部署前检查清单,https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/,"Direct resource sharing works best in existing relationships where the reader is already actively trying to deploy or self-host something and would value an execution asset over a public article.",planned,"Planned action: send to 1 to 2 people who recently discussed deployment or self-hosting. Use checklist directly only when the context is already execution-focused." +2026-04-07,email_update,部署一个 GitHub 项目前,最应该先确认的 10 件事,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"A low-frequency subscriber update is the cheapest owned-audience test for whether existing trust converts into article clicks and checklist interest.",planned,"Planned action: send 1 low-frequency deployment-topic update linking article 1 and optionally the checklist as the next step." diff --git a/docs/topic-ledger.csv b/docs/topic-ledger.csv index 7b49b200c..d3a269343 100644 --- a/docs/topic-ledger.csv +++ b/docs/topic-ledger.csv @@ -1,7 +1,8 @@ date_published,topic_cluster,content_title,content_type,status,canonical_url,primary_problem,search_intent_level,primary_cta,asset_target,next_step,page_views,cta_clicks,asset_unlocks_or_downloads,confirmed_subscribers,welcome_email_opens,welcome_email_clicks,replies_or_feedback,product_interest_signals,paid_conversions,proof_summary,what_worked,what_failed,next_iteration,notes ,deployment,Homepage checklist CTA,resource_page,published,https://www.fzhang.dev/,"Make the site immediately point readers toward a reusable execution asset instead of leaving them in general blog navigation.",medium,领取免费清单,deployment-checklist,Click through to checklist page,,,,,,,,,,,Seed row for homepage-to-checklist path,Use as entry point baseline -,deployment,开源 AI 项目部署前检查清单,resource_page,published,https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/,"Convert deployment-intent readers into checklist unlocks and confirmed subscribers.",high,领取免费清单,deployment-checklist,Unlock checklist and confirm subscription,,,,,,,,,,,Primary capture page for current funnel, +,deployment,开源 AI 项目部署前检查清单,resource_page,published,https://www.fzhang.dev/resources/open-source-ai-deployment-checklist/,"Convert deployment-intent readers into checklist unlocks and confirmed subscribers.",high,领取免费清单,deployment-checklist,Unlock checklist and confirm subscription,,,,,,,,,,,Primary capture page for current funnel,Main resource page; default as post-click destination rather than cold-start distribution asset ,deployment,Checklist success / confirmation page,success_page,published,https://www.fzhang.dev/checklist-sent/,"Bridge resource unlock intent into confirmation, welcome flow, and later low-frequency topic emails.",medium,下载 Markdown 版清单,deployment-checklist,Confirm subscription or continue reading,,,,,,,,,,,Track post-submit dropoff and confirmation behavior, -2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster, -,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_LocalRunsButServerBreaks.md, -,deployment,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,article,draft,,"Bridge deployment-intent readers from checklist thinking into SOP-level prioritization and risk sequencing.",high,先领清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_RisksMustHandleFirst.md, +2026-03-31,deployment,部署一个 GitHub 项目前,最应该先确认的 10 件事,article,published,https://www.fzhang.dev/posts/deploy-github-project-10-checks/,"Capture high-intent readers who are actively evaluating whether and how to deploy a GitHub project.",high,领取开源 AI 项目部署前检查清单,deployment-checklist,Click from article to checklist page,,,,,,,,,,,First published article in deployment cluster,P1 distribution asset for the first validation cycle +,deployment,为什么很多开源 AI 项目“本地能跑”,一上服务器就出问题?,article,draft,,"Explain the gap between local success and real deployment readiness, then push readers into the checklist path.",high,先用部署前检查清单过一遍,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_LocalRunsButServerBreaks.md,P1 distribution asset after publish; strongest problem-amplification article +,deployment,开源 AI 项目上线前,哪些风险必须先处理,哪些可以后补?,article,draft,,"Bridge deployment-intent readers from checklist thinking into SOP-level prioritization and risk sequencing.",high,先领清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Draft asset created at docs/assets/Article_RisksMustHandleFirst.md,P2 bridge article; activate after first distribution sample exists +,deployment,域名、HTTPS、反代、鉴权:第一次公开上线前最容易漏掉什么?,article,draft,,"Capture readers who are already closer to public launch and need concrete edge-case reminders before exposure.",high,下载清单,deployment-checklist,Checklist click and later SOP interest,,,,,,,,,,,Planned article in batch 1,Use after the bridge article starts surfacing deeper hardening intent From fcca4b0b492ed67c64b44d8da8229974a3c5bdcc Mon Sep 17 00:00:00 2001 From: frank_zhang <34300746+pa4uslf@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:47:00 +0800 Subject: [PATCH 27/27] Add optional scraper archive checksum verification --- config.example.json | 1 + src/classes/Outreach.py | 17 +++++++++++++++-- src/config.py | 10 ++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/config.example.json b/config.example.json index ac6d9b9c3..178739862 100644 --- a/config.example.json +++ b/config.example.json @@ -13,6 +13,7 @@ "zip_url": "", "is_for_kids": false, "google_maps_scraper": "https://github.com/gosom/google-maps-scraper/archive/refs/tags/v0.9.7.zip", + "google_maps_scraper_sha256": "", "email": { "smtp_server": "smtp.gmail.com", "smtp_port": 587, diff --git a/src/classes/Outreach.py b/src/classes/Outreach.py index f6f6d1303..2ea68c128 100644 --- a/src/classes/Outreach.py +++ b/src/classes/Outreach.py @@ -5,6 +5,7 @@ import time import glob import shlex +import hashlib import zipfile import yagmail import requests @@ -74,8 +75,20 @@ def unzip_file(self, zip_link: str) -> None: info("=> Scraper already unzipped. Skipping unzip.") return - r = requests.get(zip_link) - z = zipfile.ZipFile(io.BytesIO(r.content)) + r = requests.get(zip_link, timeout=60) + r.raise_for_status() + archive_bytes = r.content + + expected_checksum = get_google_maps_scraper_sha256() + if expected_checksum: + archive_checksum = hashlib.sha256(archive_bytes).hexdigest() + if archive_checksum.lower() != expected_checksum.lower(): + raise ValueError( + "Downloaded Google Maps scraper archive checksum does not match " + "google_maps_scraper_sha256." + ) + + z = zipfile.ZipFile(io.BytesIO(archive_bytes)) for member in z.namelist(): if ".." in member or member.startswith("/"): warning(f"Skipping suspicious path in archive: {member}") diff --git a/src/config.py b/src/config.py index fb26d8d4e..d0d019dc3 100644 --- a/src/config.py +++ b/src/config.py @@ -183,6 +183,16 @@ def get_google_maps_scraper_zip_url() -> str: with open(os.path.join(ROOT_DIR, "config.json"), "r") as file: return json.load(file)["google_maps_scraper"] +def get_google_maps_scraper_sha256() -> str: + """ + Gets the optional SHA256 checksum for the Google Maps scraper archive. + + Returns: + checksum (str): Expected SHA256 checksum or empty string + """ + with open(os.path.join(ROOT_DIR, "config.json"), "r") as file: + return str(json.load(file).get("google_maps_scraper_sha256", "")).strip() + def get_google_maps_scraper_niche() -> str: """ Gets the niche for the Google Maps scraper.