kr-research-site
Skill2 starsChanged 9 days agoMITView on GitHub
Build and deploy the author's own static research site (canonical home for finished Korean/U.S. stock and sector memos) with SEO/AEO outputs (canonical, OG, JSON-LD Article/Breadcrumb/FAQ, sitemap.xml, Atom feed, robots.txt, llms.txt, llms-full.txt), opt-in AdSense slots, and IndexNow pings. Use when the user wants a memo published to the website, wants the site rebuilt after a memo update, wants a local preview, or wants a Naver teaser that links back to the site. Only memos listed in site/published.json are built; untracked, private-path, holdings/ledger, or undated memos are refused. Do not use to write analysis or to publish to Naver itself (kr-naver-blog-publish does that).
In this repository42 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- kr-analyst-report-discoverSkill
- kr-analyst-report-fetchSkill
- kr-analyst-report-insightSkill
- kr-analyst-report-watchSkill
- kr-article-readabilitySkill
- kr-chatgpt-reviewSkill
- kr-daily-market-newsSkill
- kr-earnings-reviewSkill
- kr-finance-slide-claritySkill
- kr-foreign-analystSkill
- kr-market-leadersSkill
- kr-market-sentimentSkill
- kr-naver-bloggerSkill
- kr-naver-blog-publishSkill
- kr-naver-browseSkill
- kr-naver-insightSkill
- kr-order-backlog-analysisSkill
- kr-portfolio-guardSkill
- kr-portfolio-monitorSkill
- kr-sector-analysisSkill
- kr-sector-auditSkill
- kr-sector-compareSkill
- kr-sector-data-packSkill
- kr-sector-planSkill
- kr-sector-updateSkill
- kr-stock-analysisSkill
- kr-stock-chartSkill
- kr-stock-dart-analysisSkill
- kr-stock-data-packSkill
- kr-stock-planSkill
- kr-stock-updateSkill
- kr-strategy-backtestSkill
- kr-trade-flow-analysisSkill
- kr-web-browseSkill
- telegram-report-senderSkill
- us-daily-market-newsSkill
- us-earnings-reviewSkill
- us-sec-analysisSkill
- us-stock-analysisSkill
- us-strategy-backtestSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 4 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 14
Opt in: Add the memo to site/published.json:
- Very specific: line 77
Only site/published.json entries are built.
- Very specific: line 79
Never put guard reports, the decision ledger, or the voice profile into site/.
- Distinctive: line 109
Write for readers of the published page.
- Distinctive: line 110
Do not display “원본 리서치 메모 보기 (Markdown)” or other implementation/source-file controls in article headers.
- Distinctive: line 113
Keep paragraphs visually separated (28px bottom margin and 1.9 line height).
- Very specific: line 142
Run npm run check:site, including real local Worker/D1 engagement tests.
- Distinctive: line 162
Place comparison, charts, calculator and management checks beside the corresponding argument.
- Very specific: line 164
When a model uses unverified price/mix/profit/multiple inputs, lead with sensitivity and put conditional valuation behind an expandable …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
KR Research Site
The site is the canonical home for finished research. Naver gets a short teaser that links back here, so the two copies are not judged as duplicates. Ads and canonical URLs live on the site.
Requires kr-naver-blog-publish installed next to this skill: the renderer reuses its memo parser (memo-to-post.js) and tone markers (color-markers.js).
Workflow
Opt in. Add the memo to
site/published.json:{ "memo": "analysis-example/us/Alphabet/memo.md", "slug": "us/alphabet-2026-q3", "company": "알파벳", "ticker": "GOOGL", "exchange": "NASDAQ", "market": "us", "tags": ["알파벳", "GOOGL"] }memoandslugare required. Optionalarticlepoints to a tracked editorial Markdown sibling; it must preserve the original memo 기준일 and passes the same privacy and image checks. The original memo remains available at<slug>/memo.mdfor compatibility, but do not show a Markdown source button or link in the public article. Setarchive: truefor historical research; cards and the article show a 기록 글 label and explain that subsequent changes are excluded. For editorial publication, setdatePublishedto the actual site publication date anddateModifiedto the latest editing date. The page displays these separately from the 자료 기준일; older entries without these fields still build.slugis lowercasea-z0-9-segments joined by/and never changes after publishing (it is the canonical URL).company,ticker,exchange,market,issue,tags,datePublished,dateModifiedoverride what the builder derives from the memo. Display-only fields (see references/design-brief.md):headline: short on-page title and card title (the SEO<title>keeps thecompany(ticker) | issue | 기준일format).summary: one-line card summary. Leave it out when the memo has a한줄요약header line, which is used automatically; older memos without one fall back to whole sentences from the core answer.stance:긍정/중립/부정(orpos/neu/neg) badge. Set it only when the memo states that call; never infer one. No buy/sell words.quote: up to 4 header cells{ "label", "value", "unit"?, "tone"?: "up" | "down" }, copied from numbers in the memo.featured: rank in the home "지금 읽을 만한 리서치" grid (1 = big card). Unranked slots fall back to the latest articles.popular: rank in the home "인기" tab. Until there are visit stats, unranked articles follow research-date order. Commit the memo and every image it embeds first; the builder refuses untracked files.
Pick the cover art. The list cover and the Kakao/OG share card use the first of these that exists:
- The article's own art:
site/covers/<slug with / as ->.jpg. coverSectoron the manifest entry: anidfromsite/cover-sectors.json, shown fromsite/covers/sectors/<id>.jpg.- The first
sectors[]value that matches a dictionarylabeloraliasesentry (case and spacing ignored). - The text cover.
A new article with an industry in
sectorsneeds nothing else. Articles outside the library (market sentiment, strategy backtests, people) need their own art. Gemini needs the logged-in browser on this machine, so generation runs here and not in Cloudflare:node skills/kr-research-site/scripts/generate-covers.js # articles no picture covers yet node skills/kr-research-site/scripts/generate-covers.js --slug <slug> --force # make or redo an article's own art node skills/kr-research-site/scripts/generate-covers.js --sectors # fill the library; resumes by skipping existing files node skills/kr-research-site/scripts/generate-covers.js --sector <id> --force # redo one sector pictureA run stops after a login page or two failures in a row, and reports how many are left. Open each new image and reject logos, brand marks or legible text, then redo it with a better description:
coverSubjecton the manifest entry, orsubjectin the dictionary. Commit the.jpg.npm run test:sitefails on a published article with no picture and on an unknowncoverSector, which also stops the Cloudflare build. To ship with the text cover (for example Gemini logged out and no matching sector), set"coverArt": falseon the entry and remove it once art is committed; it also turns off the sector fallback. When too many cards in a sector look alike, make own art for the newer articles.- The article's own art:
Review readability, then build and check.
For every new or edited article, apply kr-article-readability. Inspect emphasis, tone colors, paragraph/section rhythm, mobile tables and source labels; save an exact-content review record. Run
npm run check:readabilitybefore deployment. Officialdeploy:preview,deploy:siteanddeploy:pagesnpm commands enforce this with predeploy lifecycle hooks. Existing legacy snapshots remain explicitly unreviewed and stop exempting an article as soon as its content/metadata changes.node skills/kr-research-site/scripts/build-site.js --out site-dist node skills/kr-research-site/scripts/serve-site.js --dir site-dist --port 8080Open the article at phone width with
/browseand check the core answer box, tables, charts, tone colors, update log and sources. Read references/seo-aeo.md for the title, description, structured data and ad placement rules the build enforces.- Deploy. Push to
main. Cloudflare Workers Builds (GitHub integration) runs the tests, builds with--productionand deployssite-dist/withnpx wrangler deploy. In parallel.github/workflows/site.ymlbuilds the pushed commit and the previous one, waits until the liveurls.jsonmatches the new build, then sends only new, changed or removed URLs to IndexNow. Naver teaser (optional).
node skills/kr-naver-blog-publish/scripts/memo-to-post.js --memo <memo.md> --mode teaser node skills/kr-naver-blog-publish/scripts/publisher.js prepare --manifest <dir>/naver-teaser-publish.jsonThe teaser holds the Summary, one key table, one chart, the canonical link (
원문 전체 보기: <url>), primary sources, the disclaimer and the signature. The canonical URL comes fromsite/site.config.jsonbaseUrl+ the memo'sslugand is recorded aspost.canonicalUrlin the manifest. Public publishing still needs the publisher's explicit approval gate.
Update flow
When kr-stock-update appends an Update Log block (### YYYY-MM-DD — ...) or bumps 최근 업데이트일, commit and push. The rebuild moves dateModified, the sitemap lastmod and the feed updated, shows the block under "업데이트 내역", and IndexNow is pinged for that URL. Write a new Naver teaser ("○○ 업데이트") only for a material update; that call is the user's.
Safety rules
- Only
site/published.jsonentries are built. Nothing else underanalysis-example/reaches the site. - The build refuses: files not tracked by git; files inside
KR_PORTFOLIO_GUARD_HOME,~/stock-analysis-privateor~/folio-private; memos or pages mentioning holdings/ledger artifacts (decision-ledger,portfolio.json,holdings.json,voice-profile.md…); memos without aYYYY-MM-DD기준일. - Never put guard reports, the decision ledger, or the voice profile into
site/. - Ads are emitted only when
adsense.clientis set insite/site.config.json. With it empty (before AdSense approval) the output contains no ad code and noads.txt. - Free, public, disclaimed research only. Paid subscriptions or one-to-one advice would turn this into 유사투자자문업 territory; do not add them here.
One-time setup (user)
- The site runs as a Cloudflare Worker with static assets (
wrangler.jsoncat the repo root uploadssite-dist/). The public canonical address ishttps://kr-research-site.pages.dev; a Pages service-binding proxy forwards requests to Workerkr-research-site. The originalhttps://kr-research-site.ray527321.workers.devpublic route and Worker preview URLs are disabled withworkers_dev: falseandpreview_urls: falsein the root Wrangler configuration. Keep the Worker itself: Pages still reaches it through the service binding. See Pages proxy operations.baseUrl(andauthor.url) insite/site.config.jsonmust match it exactly. Administrator access uses a separate password stored in the Worker SecretADMIN_PASSWORD; Cloudflare Access setup is not required. Keep public pages open. A custom domain can be attached later, but that changes every canonical URL, so decide before the site is indexed. - Cloudflare dashboard → Workers & Pages → Create → Import a repository → this repository:
- Project (Worker) name:
kr-research-site(must equalnameinwrangler.jsonc) - Build command:
npm ci && npm run check:site - Deploy command:
npm run deploy:site(validates analytics settings, applies remote D1 migrations, deploys Worker) - Advanced settings → Build variables:
NODE_VERSION=22; Build watch paths:site/*,analysis-example/*,skills/kr-research-site/*,skills/kr-article-readability/*,skills/kr-naver-blog-publish/scripts/*,wrangler.jsonc,package*.json - Let Cloudflare create the build API token automatically. No GitHub secrets are needed.
- Project (Worker) name:
- Register the site in Google Search Console (URL-prefix property), 네이버 서치어드바이저 and Bing Webmaster. A
pages.devsite has no DNS of its own, so use the HTML meta-tag method: put each token inverification.google/.naver/.bing, push, then verify and submit/sitemap.xml. - Generate an IndexNow key and set
indexNow.key. - AdSense site registration must accept the public hostname before proceeding. Google permits eligible platform subdomains on the Public Suffix List; purchasing a domain is not a universal requirement. In this account,
kr-research-site.ray527321.workers.devwas rejected as an ordinary subdomain and the suggested account root returned 404. Usehttps://kr-research-site.pages.devfor the next registration attempt; acceptance and content approval must be confirmed in the actual AdSense account. Do not promise approval or infer a minimum article count. Once the user supplies the real publisher ID, configure ownership verification and ads.txt; ad slots require the actual account slot IDs. Configure the appropriate consent message in AdSense before ad serving.
Scripts
| Script | Purpose | |
scripts/build-site.js | Build site-dist/ from opt-in memos + site/pages/*.md (articles, list pages, tag pages, sitemap, feed, robots, llms, urls.json, ads.txt, IndexNow key file) | |
scripts/serve-site.js | Local static preview server | |
scripts/indexnow-ping.js | POST changed URLs to IndexNow endpoints (--dry-run, --all, `--previous <url | file>`) |
scripts/test-build-site.js | Fixture tests: HTML/JSON-LD, sitemap/feed, opt-in and private-path refusals, ads on/off |
Public article editing rules
- Omit entirely empty chart series and research-progress placeholders such as “자료 확인 중” from public articles. Keep missing values in research data and retain limitations that materially affect the conclusion in the prose or source notes.
- Write for readers of the published page. Omit local file names, JSON inputs/results, Python scripts, CSV zone files, reproduction commands and internal research-pipeline status from prose. Keep these in repository research artifacts; retain disclosed facts, assumptions, source dates and material verification limits.
- Do not display “원본 리서치 메모 보기 (Markdown)” or other implementation/source-file controls in article headers.
- Evidence links must not read as body text. Put them right after the sentence or in the table cell they support (
...유지했다. [하나증권 브리핑](url)), never as a separate paragraph of their own. The builder shows these, parenthetical links and any standalone link as the number only and keeps the label in the source list; a link keeps its label only when the sentence needs the name ([Fortune](url)은 ...). - Bare numeric citations such as
[1]must resolve to their explicitly numbered Sources entry and render as links to the lower source list. Preserve source identity if the builder renumbers citations; never silently link to a different source. Code snippets and numeric labels on real Markdown links are not bare citations. - Keep paragraphs visually separated (28px bottom margin and 1.9 line height); allow clear pauses before section headings and around tables. Check long finance tables at phone width without narrowing the page or compressing prose.
- For multi-part explanations, make numbered subheadings visibly distinct from body text (top rule, space before the heading and stronger type). Group closely related facts into one or two sentences per paragraph; do not automatically split every sentence into a separate paragraph. Keep short judgment/transition paragraphs where the argument changes. Avoid repetitive “사실:” / “계산:” labels in public prose; communicate the distinction naturally while preserving assumptions and attribution.
- Numbered topic/checkpoint titles must use actual Markdown headings (
### 1. ...), not standalone bold paragraphs (**1. ...**). This applies to closing checklists as well as the main analysis; verify that each title renders as a heading with the shared separator and spacing. - Avoid dry runs of unconnected numeric paragraphs. When an argument mixes expenditure, guidance and derived values, use a compact table that labels period and fact/forecast/calculation, then explain their connection in prose. Put attributed management commentary in a visually distinct block labeled “회사 설명 · 실적 콜 요약” with its source. Summaries/paraphrases must be labeled as such, never presented as verbatim quotation; use quotation marks only for verified exact wording (and label translations). Distinguish company commentary from the author's interpretation through structure, not by coloring every sentence.
- Apply financial readability throughout the article, especially reverse valuation, scenario math, cash-flow derivations and broker revisions. Show the key result first, compact assumptions/comparisons next, and each necessary formula on its own line. Keep long caveats outside tables and explain the implication without repeating every value. A layout-only edit freezes facts, source dates and judgment.
- Apply editorial structure across every public article: compare broker targets/ratings in tables (retain unknowns and source limitations), separate company/broker/report summaries from author interpretation, and use tables for repeated financial periods, forecasts and schedules when they aid comparison. Keep causal reasoning as prose and avoid duplicating the entire table in text. Do not invent per-row source attribution when the original only supplies collective sources.
- Public tables use consistent left alignment for headers and cells, overriding Markdown alignment hints. Keep text legible and horizontal scrolling inside the table on narrow screens.
Consent analytics and administrator
The Worker serves administrator data and assets only after verifying an origin-bound signed session cookie from /admin/login. The login password comes from the Worker Secret ADMIN_PASSWORD (12–256 characters), and the session signature also uses ANALYTICS_HMAC_SECRET. Sessions last 8 hours and password rotation invalidates existing sessions. Login/logout enforce same-origin POST; login attempts have a persistent global limit of 20 per 15-minute fixed window without storing IP addresses. It fails closed with missing settings. Public static assets contain no administrator HTML/JS. The build emits analytics-manifest.json containing public paths, titles, markets and tags only; never add private memo paths or admin URLs to it, sitemap, feeds, or search artifacts.
The public footer has 통계 설정 and equal-weight consent choices. Collection starts only after opt-in. Browser IDs live at most 90 days and the server stores HMAC values; raw events expire after 90 days and identifier-free daily aggregates after 365 days. Hourly Cron rebuilds the latest 2 days plus today. The dashboard shows only observed consenting-browser traffic, KST date ranges, provisional today, missing data, collection and aggregation health, and sample-gated rules.
Read analytics operations before initial deployment. Required real settings are D1 database ID and Worker Secrets ADMIN_PASSWORD and ANALYTICS_HMAC_SECRET. Do not deploy placeholders. Use npm run check:site for static build, tracker consent tests and real local D1/Worker security/aggregation tests. Use npm run deploy:site after the account and Worker Secrets have been configured. Local static preview does not supply the protected administrator API.
Discovery and reader participation
- Optional
sectors: string[]insite/published.jsondrives related articles independently of tags. Prefer explicit industry labels, including across markets and stock/sector posts. Up to four related posts appear before publication-order previous/next links, then comments. Publication ties follow manifest order; edits never change these neighbors. - The share row's 요약+링크 복사 copies a build-time digest (
#share-digest: headline, 기준일, core answer, one key table, canonical link, disclaimer) as HTML for the Naver blog editor plus plain text. New articles must satisfy its pre-deploy rules — conclusion-first lead section, ≥60-character core answer, at least one table, bold closed within its paragraph — enforced bykr-article-readability. - Supply a short
headlineand factual publicsummary; lists, search and sharing use that same summary./search/?q=…searches only the public static metadata index, with NFKC/case normalization, substring AND matching and exact company/ticker priority. The search page is noindex. - Build-generated 1200×630 share cards use
@napi-rs/canvasand the bundled OFL Korean font. They composite the reviewed art fromsite/covers/(own or sector picture, see step 2) under the title, and fall back to a text card without art; content/font/renderer/art hashes invalidate image URLs. OG/Twitter metadata is in server HTML. Do not commit generative images without reviewing them. - Kakao uses the public JavaScript key from
kakao.javascriptKeyor build environmentKAKAO_JAVASCRIPT_KEY. Configure SDK/web domains forbaseUrl. Verify the production domain registrations, build variable and previews after deployment without automatically sending messages. - Public sharing and nickname comments are served by the existing Worker/D1. Counts fail to
—, not zero. Comments are plain text, 30/2,000 characters, pending approval, oldest first in 20-row cursor pages. Admin approval/deletion lives at/admin/comments/behind the existing signed cookie. Never bundle admin HTML/JS in public assets. - Run
npm run check:site, including real local Worker/D1 engagement tests. Keep privacy text and operations aligned with behavior. Deploy through the existing migration-first script; never reset cumulative shares with visit retention.
Historical archive publication
When the user publishes notes as records of their time, preserve original prices, assumptions, judgments and each metric's stated date. Include updates already recorded in the memo; do not refresh the analysis to the site publication day. Publish one editorial copy of each finished primary note, avoiding duplicate voice/SEO/channel copies and supporting data packs. Include uncommitted finished notes only as an explicitly scoped snapshot in the isolated publication worktree; leave the source worktree untouched.
List pages sort by the latest original research date (the maximum of 기준일, 최근 업데이트일 and dated Update Log headings), then original 기준일 and slug. Site publication/editing dates do not change that order. Keep the original 기준일 visible and label a later research update separately. For a bulk archive publication, remove old featured ranks so home recommendations also show the latest research; retain optional ranking support for deliberate future curation. Feeds and sitemap modification dates still reflect actual site edits.
Retain source bibliographic entries even when the original supplies no URL. Link numbered citations to those entries without inventing external URLs; an explicit DART receipt identifier may link to that exact filing. Preserve chart data and images, encode spaces in Markdown image paths, and verify every embedded image reaches the build.
Earnings research tools
Optional articleType, period, companyId and analysisData extend existing opt-in entries without changing legacy requirements. Follow the public earnings data contract and the common analysis standard. The build emits /earnings/ and company histories; assumptions and missing evidence must remain visible.
Keep numeric comparisons in compact tables and place lengthy broker opinions in full-width report cards. Use the Markdown columns 작성일 | 증권사·원문 | 당시 의견·목표가 | 핵심 의견 to invoke the shared renderer: the first two reports are visible and older reports use a native, keyboard-accessible disclosure. Order reports newest first; preserve dates, ratings, targets, explanations and source links. Move lengthy exceptions below numeric tables as notes. See broker opinion presentation and the POSCO Future M example.
Earnings reviews must include conference-call Q&A, following the shared sourcing and quotation standard. Use consecutive ### Q1. …, ### Q2. … subheadings to invoke shared Q&A cards. Follow each with **회사 답변 요약:** (or **회사 답변:** for a verified quotation), then **분석:** or **다음 확인:**. Show a numbered badge, a distinct answer surface and a separated follow-up, with source links and explicit summary/quotation labels. Keep cards expanded and readable in a single column on mobile. Preserve unanswered questions and connect new management targets to follow-up checks; do not display long Q&A in narrow table cells.
Earnings layout and review fixes
- Place comparison, charts, calculator and management checks beside the corresponding argument. Avoid an uninterrupted tools block before the narrative or a second copy of the same comparison table. The builder places supported earnings sections contextually; unmatched tools retain a fallback section.
- On phones, show the earnings comparison as metric cards with explicit labels; show long management checks as cards. Preserve desktop numeric comparison and accessible source links.
- When a model uses unverified price/mix/profit/multiple inputs, lead with sensitivity and put conditional valuation behind an expandable section. A dated disclosed debt balance remains a historical balance, not the future forecast. Keep company answers separate from source comparisons and author caution.
- First-analysis checks should say when the new hypothesis will be verified. A future management target is “검증시점 미도래”, not a failed promise.
- Static previews retain local link copy but remove live comment forms, count controls and analytics settings when the corresponding scripts/APIs are excluded. Run
npm run test:previewwith the site tests.
Shared preview address
Use npm run deploy:preview for review deployments from any working branch or PR. It builds the isolated static preview and always deploys to Pages branch preview, maintaining https://preview.kr-research-site.pages.dev/ as the shared review address. Do not substitute the Git/PR branch in --branch; the last completed preview deployment replaces the shared preview. Per-deployment hash URLs are for historical comparisons. Preserve production main, canonical URLs, noindex and the preview exclusions for ads/analytics/Worker APIs. See preview operations.
Portfolio strategy classification
Use articleType: "portfolio-strategy" for portfolio rules, systematic strategy backtests and recurring strategy reviews. Keep market as kr or us; never move a published slug or canonical URL to change classification. Desktop and mobile navigation place 포트폴리오 전략 immediately after 실적 리뷰. /strategies/, /strategies/kr/ and /strategies/us/ are reserved public collection paths with native 전체·한국·미국 links, counts, research-date ordering and an empty state.
Strategy posts stay in home, search, tags and feeds, but are excluded from country research lists. Home's 전체 count includes strategies and excludes earnings reviews; country filter counts exclude both, and the strategy count matches its collection. List and search rows show both country and strategy type; the public search index includes articleType. Strategy articles activate the strategy menu and show 홈 → 포트폴리오 전략 → 국가, followed by the article in BreadcrumbList. Include all three collection URLs in sitemap, urls.json and the public analytics path manifest. Preserve original prose, dates and archive labels when reclassifying existing posts.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

