sync-upstream-feature

star 4.2k

Use when porting a feature from the closed-source Shiroi repo to the open-source Shiro repo. Triggers on "sync from upstream", "port feature from Shiroi", "bring X from Shiroi to Shiro", or any task requiring code migration between the two repos.

Innei By Innei schedule Updated 3/9/2026

name: sync-upstream-feature description: Use when porting a feature from the closed-source Shiroi repo to the open-source Shiro repo. Triggers on "sync from upstream", "port feature from Shiroi", "bring X from Shiroi to Shiro", or any task requiring code migration between the two repos.

Sync Upstream Feature

Overview

Port features stripped during Shiroi-to-Shiro sync back into the open-source repo. The closed-source Shiroi repo lives at /Users/innei/git/innei-repo/Shiroi, the open-source Shiro at /Users/innei/git/innei-repo/Shiro.

Repo Layout

Repo Path Role
Shiro /Users/innei/git/innei-repo/Shiro Open-source, primary working dir
Shiroi /Users/innei/git/innei-repo/Shiroi Closed-source upstream, read-only reference

Both share the same monorepo structure (apps/web/src/...). Shiroi is the superset.

Workflow

digraph sync {
  rankdir=TB;
  node [shape=box];

  explore [label="1. Explore: find target code in both repos"];
  diff [label="2. Diff: identify what Shiroi has that Shiro lacks"];
  layers [label="3. Map all touchpoints across layers"];
  deps [label="4. Add dependencies (package.json)"];
  core [label="5. Port core components"];
  integrate [label="6. Wire into routing (Content, Markdown, page)"];
  api [label="7. Sync API query params"];
  style [label="8. Sync conditional styling"];
  lint [label="9. Lint/typecheck modified files only"];
  review [label="10. Code review via Codex"];

  explore -> diff -> layers -> deps -> core -> integrate -> api -> style -> lint -> review;
}

1. Explore Both Repos

Use parallel Explore agents to search the target feature keyword in both repos. Identify:

  • Which files exist in Shiroi but not Shiro
  • Which files exist in both but differ
  • Which dependencies Shiroi has that Shiro lacks

2. Diff: Identify the Gap

Compare key files side-by-side. Focus on:

  • Component files: Shiroi may have extra renderers, wrappers, or providers
  • Routing files (*Content.tsx): Shiroi branches on a discriminator (e.g. contentFormat), Shiro always takes one path
  • Lazy-load entries (*Markdown.tsx): Used in preview/peek contexts, often overlooked
  • API query definitions (queries/definition/*.ts): Shiroi may pass extra params (e.g. prefer: 'lexical')
  • Server-side API files (api.ts): Direct apiClient calls may also need params

3. Map All Touchpoints

A feature typically spans these layers (check ALL):

Layer Files What to sync
Dependencies package.json, pnpm-lock.yaml New npm packages
Core components components/ui/... Rendering logic
Route renderers *LexicalRenderer.tsx, etc. Per-route wrappers
Content branching *Content.tsx contentFormat discriminator
Lazy-load entries *Markdown.tsx Dynamic import + branching for preview/peek
API queries queries/definition/*.ts Query params like prefer
Server API app/[locale]/.../api.ts Direct apiClient calls
Conditional styles page.tsx, layout.tsx prose class gating
TOC / headings TocHeadingStrategy.tsx Already wired, verify

4. Add Dependencies

Read Shiroi's package.json, extract only the packages needed for rendering (not editing/dashboard). Add to Shiro's package.json alphabetically, then pnpm install.

5. Port Core Components

Copy from Shiroi, adapting for Shiro:

  • Remove Shiroi-exclusive wrappers (e.g. LexicalCommentWrapper is sponsorship-only)
  • Check that all ~/ imports resolve in Shiro (modal types, hooks, constants)
  • Fix any API mismatches (e.g. contentClassName prop may not exist in Shiro's modal types)

6. Wire Into Routing

Three integration points per content type (note/post/page):

*Content.tsx (server component entry):

if (contentFormat === 'lexical') return <XxxLexicalRenderer />
return <XxxMarkdownRenderer />

*Markdown.tsx (lazy-load entry for preview/peek):

const XxxLexicalRenderer = dynamic(() => import('./XxxLexicalRenderer').then(m => m.XxxLexicalRenderer))
// ... branch on contentFormat from data selector

page.tsx / layout.tsx (conditional prose):

className={clsx(data.contentFormat !== 'lexical' && 'prose')}

7. Sync API Query Params

Compare queries/definition/*.ts and app/.../api.ts between repos. Add missing params (e.g. prefer: 'lexical').

8. Lint and Verify

  • Lint only modified files: pnpm exec eslint --fix <files>
  • Typecheck: pnpm exec tsc --noEmit — ignore pre-existing errors, verify new files don't appear in output

Common Mistakes

Mistake Fix
Only update *Content.tsx, forget *Markdown.tsx Markdown.tsx is the lazy entry for preview/peek — always update both
Forget API prefer param Backend won't return rich content without it
Copy Shiroi-only wrappers verbatim Strip sponsorship features (comment anchoring, AI, etc.)
Leave prose class unconditional Rich content has its own typography — gate with contentFormat
Add editing dependencies when only rendering needed Only port what's required for the read path
Install via CLI
npx skills add https://github.com/Innei/Shiro --skill sync-upstream-feature
Repository Details
star Stars 4,207
call_split Forks 873
navigation Branch main
article Path SKILL.md
More from Creator