[{"data":1,"prerenderedAt":1411},["ShallowReactive",2],{"navigation":3,"doc-/frontend/module-anatomy":217,"docs-all-paths":1357},[4,19,39,63,87,111,127,195,211],{"title":5,"path":6,"stem":7,"children":8},"Welcome","/welcome","01.welcome",[9,11,15],{"title":5,"path":6,"stem":10},"01.welcome/index",{"title":12,"path":13,"stem":14},"Astar とは（5分）","/welcome/product-in-5-min","01.welcome/01.product-in-5-min",{"title":16,"path":17,"stem":18},"事業文脈","/welcome/business-context","01.welcome/02.business-context",{"title":20,"path":21,"stem":22,"children":23},"Getting Started","/getting-started","02.getting-started",[24,27,31,35],{"title":25,"path":21,"stem":26},"はじめかた","02.getting-started/index",{"title":28,"path":29,"stem":30},"リポジトリ取得と環境構築","/getting-started/repo-setup","02.getting-started/01.repo-setup",{"title":32,"path":33,"stem":34},"日々の開発ループ","/getting-started/dev-loop","02.getting-started/02.dev-loop",{"title":36,"path":37,"stem":38},"検証の 4 層","/getting-started/verification-tiers","02.getting-started/03.verification-tiers",{"title":40,"path":41,"stem":42,"children":43},"Architecture","/architecture","03.architecture",[44,47,51,55,59],{"title":45,"path":41,"stem":46},"アーキテクチャ","03.architecture/index",{"title":48,"path":49,"stem":50},"マルチテナンシーと RLS","/architecture/multi-tenancy-rls","03.architecture/01.multi-tenancy-rls",{"title":52,"path":53,"stem":54},"認可モデル","/architecture/authorization","03.architecture/02.authorization",{"title":56,"path":57,"stem":58},"AI サブシステム","/architecture/ai-subsystem","03.architecture/03.ai-subsystem",{"title":60,"path":61,"stem":62},"データモデル","/architecture/data-model","03.architecture/04.data-model",{"title":64,"path":65,"stem":66,"children":67},"Backend","/backend","04.backend",[68,71,75,79,83],{"title":69,"path":65,"stem":70},"バックエンド","04.backend/index",{"title":72,"path":73,"stem":74},"層構造","/backend/layering","04.backend/01.layering",{"title":76,"path":77,"stem":78},"規約","/backend/conventions","04.backend/02.conventions",{"title":80,"path":81,"stem":82},"テスト","/backend/testing","04.backend/03.testing",{"title":84,"path":85,"stem":86},"マイグレーション","/backend/migrations","04.backend/04.migrations",{"title":88,"path":89,"stem":90,"children":91},"Frontend","/frontend","05.frontend",[92,95,99,103,107],{"title":93,"path":89,"stem":94},"フロントエンド","05.frontend/index",{"title":96,"path":97,"stem":98},"モジュール内部構造","/frontend/module-anatomy","05.frontend/01.module-anatomy",{"title":100,"path":101,"stem":102},"API アクセスの一本道","/frontend/api-access-chain","05.frontend/02.api-access-chain",{"title":104,"path":105,"stem":106},"i18n","/frontend/i18n","05.frontend/03.i18n",{"title":108,"path":109,"stem":110},"デザインシステム","/frontend/design-system","05.frontend/04.design-system",{"title":112,"path":113,"stem":114,"children":115},"Go Agent And Cli","/go-agent-and-cli","06.go-agent-and-cli",[116,119,123],{"title":117,"path":113,"stem":118},"Go agent と CLI","06.go-agent-and-cli/index",{"title":120,"path":121,"stem":122},"Go agent","/go-agent-and-cli/go-agent","06.go-agent-and-cli/01.go-agent",{"title":124,"path":125,"stem":126},"CLI","/go-agent-and-cli/cli","06.go-agent-and-cli/02.cli",{"title":128,"path":129,"stem":130,"children":131},"Modules","/modules","07.modules",[132,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191],{"title":133,"path":129,"stem":134},"モジュール","07.modules/index",{"title":136,"path":137,"stem":138},"テーブル","/modules/table","07.modules/01.table",{"title":140,"path":141,"stem":142},"ドキュメントツリー","/modules/document","07.modules/02.document",{"title":144,"path":145,"stem":146},"AIチャット","/modules/ai","07.modules/03.ai",{"title":148,"path":149,"stem":150},"認証・権限","/modules/auth","07.modules/04.auth",{"title":152,"path":153,"stem":154},"AI取込","/modules/organize","07.modules/05.organize",{"title":156,"path":157,"stem":158},"ストレージ","/modules/storage","07.modules/06.storage",{"title":160,"path":161,"stem":162},"NAS同期","/modules/sync","07.modules/07.sync",{"title":164,"path":165,"stem":166},"ワークスペース","/modules/workspace","07.modules/08.workspace",{"title":168,"path":169,"stem":170},"テナントとメンバーシップ","/modules/tenant-membership","07.modules/09.tenant-membership",{"title":172,"path":173,"stem":174},"検索","/modules/search","07.modules/10.search",{"title":176,"path":177,"stem":178},"表示ビュー","/modules/display","07.modules/11.display",{"title":180,"path":181,"stem":182},"テンプレート","/modules/template","07.modules/12.template",{"title":184,"path":185,"stem":186},"メール","/modules/mail","07.modules/13.mail",{"title":188,"path":189,"stem":190},"電話","/modules/phone","07.modules/14.phone",{"title":192,"path":193,"stem":194},"リアルタイム","/modules/realtime","07.modules/15.realtime",{"title":196,"path":197,"stem":198,"children":199},"Infra And Deploy","/infra-and-deploy","08.infra-and-deploy",[200,203,207],{"title":201,"path":197,"stem":202},"インフラとデプロイ","08.infra-and-deploy/index",{"title":204,"path":205,"stem":206},"環境の種類","/infra-and-deploy/environments","08.infra-and-deploy/01.environments",{"title":208,"path":209,"stem":210},"セルフホスト構成","/infra-and-deploy/self-host","08.infra-and-deploy/02.self-host",{"title":212,"path":213,"stem":214,"children":215},"docs-map","/docs-map","09.docs-map/index",[216],{"title":212,"path":213,"stem":214},{"id":218,"title":96,"body":219,"description":1352,"extension":1353,"meta":1354,"navigation":659,"path":97,"seo":1355,"stem":98,"__hash__":1356},"docs/05.frontend/01.module-anatomy.md",{"type":220,"value":221,"toc":1341},"minimark",[222,225,248,256,262,272,278,360,364,381,563,575,579,588,842,849,853,861,915,973,987,1010,1014,1021,1024,1066,1077,1167,1173,1184,1195,1198,1288,1303,1316,1319,1337],[223,224,96],"h1",{"id":96},[226,227,228,229,233,234,237,238,237,241,237,244,247],"p",{},"Astar Management のフロントエンドは ",[230,231,232],"code",{},"app/modules/\u003Cdomain>/"," に46個のドメインモジュールを持ちます。1モジュール = 1業務ドメイン（",[230,235,236],{},"tag",", ",[230,239,240],{},"table",[230,242,243],{},"document",[230,245,246],{},"ai"," …）です。このページでは、モジュール1つの中身がどう構成されるか、そしてモジュールをまたぐ import に何が許され何が禁止されているかを説明します。",[249,250,252,253],"h2",{"id":251},"最小完全例-appmodulestag","最小完全例: ",[230,254,255],{},"app/modules/tag/",[226,257,258,259,261],{},"タグ付け機能を担当する ",[230,260,236],{}," モジュールは、規約に最も忠実で、かつ小さく完結しています。新しいモジュールを作るときも、既存モジュールの構造を確認するときも、まずここを見てください。",[263,264,269],"pre",{"className":265,"code":267,"language":268},[266],"language-text","app/modules/tag/\n├── index.ts                        # モジュールの公開 API（barrel export）\n├── types/\n│   └── index.ts                    # 3層の型定義（下記参照）\n├── components/\n│   ├── index.ts\n│   ├── TagChip.vue                 # Presentational: props/emits のみ\n│   └── TagPicker.vue               # Wrapper: foundation コンポーネント + ドメインロジック\n├── composables/\n│   ├── index.ts\n│   ├── useTagManagement.ts         # TanStack Query によるタグ CRUD\n│   └── useEntityTags.ts            # エンティティへのタグ付け状態\n├── repositories/\n│   ├── index.ts\n│   └── TagRepository.ts            # useApi() + apiRequest() による API 呼び出し\n└── utils/\n    ├── tagTreeBuilder.ts\n    └── __tests__/tagTreeBuilder.test.ts\n","text",[230,270,267],{"__ignoreMap":271},"",[226,273,274,277],{},[230,275,276],{},"index.ts"," は各サブディレクトリを re-export するだけの薄い barrel です。",[263,279,283],{"className":280,"code":281,"language":282,"meta":271,"style":271},"language-typescript shiki shiki-themes github-light github-dark","// app/modules/tag/index.ts\nexport * from './types'\nexport * from './components'\nexport * from './repositories'\nexport * from './composables'\nexport * from './utils/tagTreeBuilder'\n","typescript",[230,284,285,294,312,324,336,348],{"__ignoreMap":271},[286,287,290],"span",{"class":288,"line":289},"line",1,[286,291,293],{"class":292},"sJ8bj","// app/modules/tag/index.ts\n",[286,295,297,301,305,308],{"class":288,"line":296},2,[286,298,300],{"class":299},"szBVR","export",[286,302,304],{"class":303},"sj4cs"," *",[286,306,307],{"class":299}," from",[286,309,311],{"class":310},"sZZnC"," './types'\n",[286,313,315,317,319,321],{"class":288,"line":314},3,[286,316,300],{"class":299},[286,318,304],{"class":303},[286,320,307],{"class":299},[286,322,323],{"class":310}," './components'\n",[286,325,327,329,331,333],{"class":288,"line":326},4,[286,328,300],{"class":299},[286,330,304],{"class":303},[286,332,307],{"class":299},[286,334,335],{"class":310}," './repositories'\n",[286,337,339,341,343,345],{"class":288,"line":338},5,[286,340,300],{"class":299},[286,342,304],{"class":303},[286,344,307],{"class":299},[286,346,347],{"class":310}," './composables'\n",[286,349,351,353,355,357],{"class":288,"line":350},6,[286,352,300],{"class":299},[286,354,304],{"class":303},[286,356,307],{"class":299},[286,358,359],{"class":310}," './utils/tagTreeBuilder'\n",[249,361,363],{"id":362},"必須4分類と-optional-な3分類","必須4分類と optional な3分類",[226,365,366,367,370,371,370,374,370,377,380],{},"どのモジュールも、最低限 ",[230,368,369],{},"components/"," ",[230,372,373],{},"composables/",[230,375,376],{},"repositories/",[230,378,379],{},"types/"," の4分類を持ちます。加えて、必要なモジュールだけが持つ optional な分類が3つあります。",[240,382,383,402],{},[384,385,386],"thead",{},[387,388,389,393,396,399],"tr",{},[390,391,392],"th",{},"ディレクトリ",[390,394,395],{},"必須/optional",[390,397,398],{},"役割",[390,400,401],{},"採用例",[403,404,405,421,434,454,467,492,515,542],"tbody",{},[387,406,407,412,415,418],{},[408,409,410],"td",{},[230,411,369],{},[408,413,414],{},"必須",[408,416,417],{},"Vue SFC。Presentational（props/emitsのみ）と Wrapper（foundation + ドメインロジック）の2種",[408,419,420],{},"全モジュール",[387,422,423,427,429,432],{},[408,424,425],{},[230,426,373],{},[408,428,414],{},[408,430,431],{},"TanStack Query によるサーバー状態管理 + ビジネスロジック",[408,433,420],{},[387,435,436,440,442,452],{},[408,437,438],{},[230,439,376],{},[408,441,414],{},[408,443,444,447,448,451],{},[230,445,446],{},"useApi()"," + ",[230,449,450],{},"apiRequest()"," による API アクセス層",[408,453,420],{},[387,455,456,460,462,465],{},[408,457,458],{},[230,459,379],{},[408,461,414],{},[408,463,464],{},"3層の型定義（下記参照）",[408,466,420],{},[387,468,469,474,477,480],{},[408,470,471],{},[230,472,473],{},"services/",[408,475,476],{},"optional（46中10）",[408,478,479],{},"composable と repository の間に挟む追加のビジネスロジック層",[408,481,482,237,484,237,486,237,488,491],{},[230,483,246],{},[230,485,243],{},[230,487,240],{},[230,489,490],{},"mail"," など",[387,493,494,499,502,505],{},[408,495,496],{},[230,497,498],{},"validators/",[408,500,501],{},"optional（46中17）",[408,503,504],{},"Zod によるフォーム/入力バリデーション",[408,506,507,237,509,237,512,491],{},[230,508,243],{},[230,510,511],{},"organize",[230,513,514],{},"billing",[387,516,517,522,525,532],{},[408,518,519],{},[230,520,521],{},"stores/",[408,523,524],{},"optional（46中5）",[408,526,527,528,531],{},"Pinia ストア（",[230,529,530],{},"defineTenantStore"," 経由。詳細は後述）",[408,533,534,237,536,237,539,491],{},[230,535,243],{},[230,537,538],{},"notification",[230,540,541],{},"storage",[387,543,544,549,552,555],{},[408,545,546],{},[230,547,548],{},"utils/",[408,550,551],{},"optional",[408,553,554],{},"純粋関数のヘルパー",[408,556,557,559,560,491],{},[230,558,236],{}," の ",[230,561,562],{},"tagTreeBuilder.ts",[226,564,565,567,568,570,571,574],{},[230,566,473],{}," を持つのは46モジュール中10個だけです。「composable → repository」がほとんどのモジュールの実際のチェーンで、",[230,569,473],{}," は業務ロジックが複雑なモジュールにだけ追加される中間層だと理解してください（詳しくは ",[572,573,100],"a",{"href":101},"）。",[249,576,578],{"id":577},"_3層の型定義","3層の型定義",[226,580,581,584,585,587],{},[230,582,583],{},"types/index.ts"," は次の3層で構成します。",[230,586,236],{}," の例:",[263,589,591],{"className":280,"code":590,"language":282,"meta":271,"style":271},"// Tier 1: OpenAPI 自動生成型（API契約 — 手で書かない）\nexport type TagResponse = components['schemas']['TagResponse']\nexport type CreateTagRequest = components['schemas']['CreateTagRequest']\n\n// Tier 2: Repository インターフェース（データアクセス契約）\nexport interface TagRepository {\n  listTags(): Promise\u003CTagResponse[]>\n  createTag(request: CreateTagRequest): Promise\u003CTagResponse>\n  deleteTag(id: string): Promise\u003Cvoid>\n}\n\n// Tier 3: ドメイン型（UI専用、API由来ではない）\nexport interface TagTreeNode {\n  id: string\n  name: string\n  children: TagTreeNode[]\n  level: number\n}\n",[230,592,593,598,631,655,661,666,679,703,734,763,769,774,780,792,803,813,826,837],{"__ignoreMap":271},[286,594,595],{"class":288,"line":289},[286,596,597],{"class":292},"// Tier 1: OpenAPI 自動生成型（API契約 — 手で書かない）\n",[286,599,600,602,605,609,612,615,619,622,625,628],{"class":288,"line":296},[286,601,300],{"class":299},[286,603,604],{"class":299}," type",[286,606,608],{"class":607},"sScJk"," TagResponse",[286,610,611],{"class":299}," =",[286,613,614],{"class":607}," components",[286,616,618],{"class":617},"sVt8B","[",[286,620,621],{"class":310},"'schemas'",[286,623,624],{"class":617},"][",[286,626,627],{"class":310},"'TagResponse'",[286,629,630],{"class":617},"]\n",[286,632,633,635,637,640,642,644,646,648,650,653],{"class":288,"line":314},[286,634,300],{"class":299},[286,636,604],{"class":299},[286,638,639],{"class":607}," CreateTagRequest",[286,641,611],{"class":299},[286,643,614],{"class":607},[286,645,618],{"class":617},[286,647,621],{"class":310},[286,649,624],{"class":617},[286,651,652],{"class":310},"'CreateTagRequest'",[286,654,630],{"class":617},[286,656,657],{"class":288,"line":326},[286,658,660],{"emptyLinePlaceholder":659},true,"\n",[286,662,663],{"class":288,"line":338},[286,664,665],{"class":292},"// Tier 2: Repository インターフェース（データアクセス契約）\n",[286,667,668,670,673,676],{"class":288,"line":350},[286,669,300],{"class":299},[286,671,672],{"class":299}," interface",[286,674,675],{"class":607}," TagRepository",[286,677,678],{"class":617}," {\n",[286,680,682,685,688,691,694,697,700],{"class":288,"line":681},7,[286,683,684],{"class":607},"  listTags",[286,686,687],{"class":617},"()",[286,689,690],{"class":299},":",[286,692,693],{"class":607}," Promise",[286,695,696],{"class":617},"\u003C",[286,698,699],{"class":607},"TagResponse",[286,701,702],{"class":617},"[]>\n",[286,704,706,709,712,716,718,720,723,725,727,729,731],{"class":288,"line":705},8,[286,707,708],{"class":607},"  createTag",[286,710,711],{"class":617},"(",[286,713,715],{"class":714},"s4XuR","request",[286,717,690],{"class":299},[286,719,639],{"class":607},[286,721,722],{"class":617},")",[286,724,690],{"class":299},[286,726,693],{"class":607},[286,728,696],{"class":617},[286,730,699],{"class":607},[286,732,733],{"class":617},">\n",[286,735,737,740,742,745,747,750,752,754,756,758,761],{"class":288,"line":736},9,[286,738,739],{"class":607},"  deleteTag",[286,741,711],{"class":617},[286,743,744],{"class":714},"id",[286,746,690],{"class":299},[286,748,749],{"class":303}," string",[286,751,722],{"class":617},[286,753,690],{"class":299},[286,755,693],{"class":607},[286,757,696],{"class":617},[286,759,760],{"class":303},"void",[286,762,733],{"class":617},[286,764,766],{"class":288,"line":765},10,[286,767,768],{"class":617},"}\n",[286,770,772],{"class":288,"line":771},11,[286,773,660],{"emptyLinePlaceholder":659},[286,775,777],{"class":288,"line":776},12,[286,778,779],{"class":292},"// Tier 3: ドメイン型（UI専用、API由来ではない）\n",[286,781,783,785,787,790],{"class":288,"line":782},13,[286,784,300],{"class":299},[286,786,672],{"class":299},[286,788,789],{"class":607}," TagTreeNode",[286,791,678],{"class":617},[286,793,795,798,800],{"class":288,"line":794},14,[286,796,797],{"class":714},"  id",[286,799,690],{"class":299},[286,801,802],{"class":303}," string\n",[286,804,806,809,811],{"class":288,"line":805},15,[286,807,808],{"class":714},"  name",[286,810,690],{"class":299},[286,812,802],{"class":303},[286,814,816,819,821,823],{"class":288,"line":815},16,[286,817,818],{"class":714},"  children",[286,820,690],{"class":299},[286,822,789],{"class":607},[286,824,825],{"class":617},"[]\n",[286,827,829,832,834],{"class":288,"line":828},17,[286,830,831],{"class":714},"  level",[286,833,690],{"class":299},[286,835,836],{"class":303}," number\n",[286,838,840],{"class":288,"line":839},18,[286,841,768],{"class":617},[226,843,844,845,848],{},"手書きの interface で API 型を代替してはいけません。OpenAPI と乖離します。Tier 1 は必ず ",[230,846,847],{},"components['schemas'][...]"," から取ります。",[249,850,852],{"id":851},"モジュールをまたぐ-import-は4つのサブバレル経由のみ","モジュールをまたぐ import は4つのサブバレル経由のみ",[226,854,855,856,860],{},"同一モジュール内の import（相対パス）は自由です。しかし ",[857,858,859],"strong",{},"別モジュールから"," あるモジュールの中身を参照するときは、必ず次の4つのサブバレルのどれかを経由しなければなりません。",[240,862,863,873],{},[384,864,865],{},[387,866,867,870],{},[390,868,869],{},"対象",[390,871,872],{},"import 元",[403,874,875,885,895,905],{},[387,876,877,880],{},[408,878,879],{},"types / utils / services / repositories / validators",[408,881,882],{},[230,883,884],{},"~/modules/\u003CX>",[387,886,887,890],{},[408,888,889],{},"composables",[408,891,892],{},[230,893,894],{},"~/modules/\u003CX>/composables",[387,896,897,900],{},[408,898,899],{},"Pinia stores",[408,901,902],{},[230,903,904],{},"~/modules/\u003CX>/stores",[387,906,907,910],{},[408,908,909],{},"Vue SFC",[408,911,912],{},[230,913,914],{},"~/modules/\u003CX>/components",[263,916,918],{"className":280,"code":917,"language":282,"meta":271,"style":271},"// Do: サブバレル経由\nimport { useTagManagement } from '~/modules/tag/composables'\nimport type { TagResponse } from '~/modules/tag'\n\n// Don't: 深い import（他モジュールからは禁止）\nimport { useTagManagement } from '~/modules/tag/composables/useTagManagement'\n",[230,919,920,925,939,953,957,962],{"__ignoreMap":271},[286,921,922],{"class":288,"line":289},[286,923,924],{"class":292},"// Do: サブバレル経由\n",[286,926,927,930,933,936],{"class":288,"line":296},[286,928,929],{"class":299},"import",[286,931,932],{"class":617}," { useTagManagement } ",[286,934,935],{"class":299},"from",[286,937,938],{"class":310}," '~/modules/tag/composables'\n",[286,940,941,943,945,948,950],{"class":288,"line":314},[286,942,929],{"class":299},[286,944,604],{"class":299},[286,946,947],{"class":617}," { TagResponse } ",[286,949,935],{"class":299},[286,951,952],{"class":310}," '~/modules/tag'\n",[286,954,955],{"class":288,"line":326},[286,956,660],{"emptyLinePlaceholder":659},[286,958,959],{"class":288,"line":338},[286,960,961],{"class":292},"// Don't: 深い import（他モジュールからは禁止）\n",[286,963,964,966,968,970],{"class":288,"line":350},[286,965,929],{"class":299},[286,967,932],{"class":617},[286,969,935],{"class":299},[286,971,972],{"class":310}," '~/modules/tag/composables/useTagManagement'\n",[226,974,975,976,979,980,559,983,986],{},"深いパスへの直接 import は SFC ツリー全体を巻き込んで引っ張ってしまい、Vitest 上で Tailwind v4 の ",[230,977,978],{},"@apply"," 変換が壊れる原因になります。この規約は現在 ",[230,981,982],{},"no-restricted-imports",[857,984,985],{},"warn"," で移行中（既存の違反は grandfathered、新規には追加しないこと）。",[226,988,989,992,993,996,997,996,1000,996,1003,1006,1007,1009],{},[230,990,991],{},"~/"," 以外のエイリアス（",[230,994,995],{},"@foundation"," / ",[230,998,999],{},"@modules",[230,1001,1002],{},"@shared",[230,1004,1005],{},"@ui","）は2026-06に廃止されています。使うのは ",[230,1008,991],{}," のみです。",[249,1011,1013],{"id":1012},"モジュール間の循環importを防ぐ-module-graph-guard","モジュール間の循環importを防ぐ Module-graph guard",[226,1015,1016,1017,1020],{},"サブバレル規約とは別に、特定のモジュール間には ",[857,1018,1019],{},"静的 import そのものが禁止"," されている組み合わせがあります。理由は SFC の循環参照（strongly-connected component）を防ぐためです。screen モジュールはほぼ全モジュールの画面を描画し、逆に document / ai / table のような重量級モジュールが screen を描画し返すと、Vite SSR / Vitest 環境で「部分評価されたモジュール namespace」によるクラッシュや、テストスイート全体のタイムアウトを引き起こしました（2026-07 に実際に発生した障害）。",[226,1022,1023],{},"禁止されている edge の例:",[1025,1026,1027,1035,1049,1058],"ul",{},[1028,1029,1030,1031,1034],"li",{},"非 screen モジュール → ",[230,1032,1033],{},"~/modules/screen/components"," の静的 import は禁止（screen 側からのみ許可）",[1028,1036,1037,1040,1041,1044,1045,1048],{},[230,1038,1039],{},"screen/**"," → ",[230,1042,1043],{},"~/modules/table/components"," の静的 import は禁止（",[230,1046,1047],{},"RecordListContainer"," という最重量 SFC subtree を引き込むため）",[1028,1050,1051,1040,1054,1057],{},[230,1052,1053],{},"table/**",[230,1055,1056],{},"~/modules/document/components"," の静的 import は禁止（document/ai editor の subtree ごと引き込むため）",[1028,1059,1060,1040,1062,1065],{},[230,1061,1039],{},[230,1063,1064],{},"~/modules/ai/composables"," の静的 import は禁止（barrel cycle になるうえ重い）",[226,1067,1068,1069,1072,1073,1076],{},"これらの seam を越える必要があるときは、",[230,1070,1071],{},"defineAsyncComponent"," で ",[857,1074,1075],{},"遅延"," import します。",[263,1078,1080],{"className":280,"code":1079,"language":282,"meta":271,"style":271},"const TableViewRenderer = Object.assign(\n  defineAsyncComponent(() =>\n    import('~/modules/screen/components').then((m) => m.TableViewRenderer)\n  ),\n  { name: 'TableViewRenderer' }, // VTU の stubs/findComponent マッチングを維持\n)\n",[230,1081,1082,1101,1112,1143,1148,1162],{"__ignoreMap":271},[286,1083,1084,1087,1090,1092,1095,1098],{"class":288,"line":289},[286,1085,1086],{"class":299},"const",[286,1088,1089],{"class":303}," TableViewRenderer",[286,1091,611],{"class":299},[286,1093,1094],{"class":617}," Object.",[286,1096,1097],{"class":607},"assign",[286,1099,1100],{"class":617},"(\n",[286,1102,1103,1106,1109],{"class":288,"line":296},[286,1104,1105],{"class":607},"  defineAsyncComponent",[286,1107,1108],{"class":617},"(() ",[286,1110,1111],{"class":299},"=>\n",[286,1113,1114,1117,1119,1122,1125,1128,1131,1134,1137,1140],{"class":288,"line":314},[286,1115,1116],{"class":299},"    import",[286,1118,711],{"class":617},[286,1120,1121],{"class":310},"'~/modules/screen/components'",[286,1123,1124],{"class":617},").",[286,1126,1127],{"class":607},"then",[286,1129,1130],{"class":617},"((",[286,1132,1133],{"class":714},"m",[286,1135,1136],{"class":617},") ",[286,1138,1139],{"class":299},"=>",[286,1141,1142],{"class":617}," m.TableViewRenderer)\n",[286,1144,1145],{"class":288,"line":326},[286,1146,1147],{"class":617},"  ),\n",[286,1149,1150,1153,1156,1159],{"class":288,"line":338},[286,1151,1152],{"class":617},"  { name: ",[286,1154,1155],{"class":310},"'TableViewRenderer'",[286,1157,1158],{"class":617}," }, ",[286,1160,1161],{"class":292},"// VTU の stubs/findComponent マッチングを維持\n",[286,1163,1164],{"class":288,"line":350},[286,1165,1166],{"class":617},")\n",[226,1168,1169,1172],{},[230,1170,1171],{},"import type { ... }"," は型のみでコンパイル時に消えるため、方向を問わず常に許可されます。",[226,1174,1175,1176,1179,1180,1183],{},"この規約は lint ではなく、",[230,1177,1178],{},"app/shared/__tests__/module-graph.guard.test.ts"," という ",[857,1181,1182],{},"ビルド失敗ゲート","（番人テスト）で強制されています。違反するとテストスイートがビルドを落とすので、CI でも確実に検知されます。",[249,1185,1187,1190,1191,1194],{"id":1186},"foundation-と-shared-の使い分け",[230,1188,1189],{},"foundation/"," と ",[230,1192,1193],{},"shared/"," の使い分け",[226,1196,1197],{},"モジュール以外に、ドメインを持たない共通コードを置く場所が2つあります。役割が違うので混同しないでください。",[240,1199,1200,1211],{},[384,1201,1202],{},[387,1203,1204,1206,1208],{},[390,1205,392],{},[390,1207,398],{},[390,1209,1210],{},"中身の例",[403,1212,1213,1253],{},[387,1214,1215,1220,1225],{},[408,1216,1217],{},[230,1218,1219],{},"app/foundation/",[408,1221,1222],{},[857,1223,1224],{},"UI プリミティブ",[408,1226,1227,1230,1231,1234,1235,1238,1239,1242,1243,237,1246,237,1249,1252],{},[230,1228,1229],{},"ui/","（shadcn-vue を ",[230,1232,1233],{},"shadcn-nuxt"," 経由で ",[230,1236,1237],{},"~/foundation/components/ui/"," に導入したもの。Button, Dialog, Accordion など）と ",[230,1240,1241],{},"common/","（Astar 独自の共通コンポーネント。",[230,1244,1245],{},"IconButton",[230,1247,1248],{},"Callout",[230,1250,1251],{},"PageHeader"," など）",[387,1254,1255,1260,1265],{},[408,1256,1257],{},[230,1258,1259],{},"app/shared/",[408,1261,1262],{},[857,1263,1264],{},"技術インフラ",[408,1266,1267,1268,1271,1272,1275,1276,1279,1280,1283,1284,1287],{},"API クライアント（",[230,1269,1270],{},"shared/api/","）、SSE（",[230,1273,1274],{},"shared/sse/","）、通知（",[230,1277,1278],{},"shared/notifications/","）、i18n 基盤（",[230,1281,1282],{},"shared/i18n/","）、テナントスコープ storage（",[230,1285,1286],{},"shared/utils/tenantScopedStorage.ts","）など",[226,1289,1290,1293,1294,1297,1298,559,1300,1302],{},[230,1291,1292],{},"foundation/common/"," のコンポーネントは ",[857,1295,1296],{},"auto-import され、prefix なし"," で使えます（",[230,1299,1233],{},[230,1301,1229],{}," も同様）。この2つは名前が衝突しやすいので、新しいコンポーネントを追加するときは既存の命名と重複していないか確認してください。",[226,1304,1305,1306,1308,1309,1311,1312,1315],{},"判断に迷ったら: 「見た目・操作の部品か」→ ",[230,1307,1189],{},"。「業務ドメインに属さないロジック・配線か」→ ",[230,1310,1193],{},"。「特定の業務ドメインに属するか」→ 該当する ",[230,1313,1314],{},"modules/\u003Cdomain>/","。",[249,1317,1318],{"id":1318},"次の一歩",[1025,1320,1321,1326,1331],{},[1028,1322,1323,1325],{},[572,1324,100],{"href":101}," — component → composable → repository のチェーンを詳しく見る",[1028,1327,1328,1330],{},[572,1329,104],{"href":105}," — テキストをどのレイヤーに置くか",[1028,1332,1333,1336],{},[572,1334,1335],{"href":129},"モジュール索引"," — 46モジュール全体の地図",[1338,1339,1340],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":271,"searchDepth":296,"depth":296,"links":1342},[1343,1345,1346,1347,1348,1349,1351],{"id":251,"depth":296,"text":1344},"最小完全例: app/modules/tag/",{"id":362,"depth":296,"text":363},{"id":577,"depth":296,"text":578},{"id":851,"depth":296,"text":852},{"id":1012,"depth":296,"text":1013},{"id":1186,"depth":296,"text":1350},"foundation/ と shared/ の使い分け",{"id":1318,"depth":296,"text":1318},"app/modules/\u003Cdomain>/ の中身（components / composables / repositories / types と optional な services / validators / stores）と、モジュール間 import のルール。","md",{},{"title":96,"description":1352},"NC6z4mw6cztFV-5DnmPEn6PI_fGHsQ-_xvgkdtotmO0",[1358,1360,1361,1363,1364,1365,1366,1367,1368,1369,1370,1371,1373,1374,1375,1376,1377,1379,1380,1381,1382,1383,1385,1387,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409],{"path":13,"title":1359},"Astar とは何か（5分で）",{"path":17,"title":16},{"path":6,"title":1362},"ようこそ",{"path":29,"title":28},{"path":33,"title":32},{"path":37,"title":36},{"path":21,"title":25},{"path":49,"title":48},{"path":53,"title":52},{"path":57,"title":56},{"path":61,"title":60},{"path":41,"title":1372},"システムアーキテクチャ",{"path":73,"title":72},{"path":77,"title":76},{"path":81,"title":80},{"path":85,"title":84},{"path":65,"title":1378},"バックエンドガイド",{"path":97,"title":96},{"path":101,"title":100},{"path":105,"title":104},{"path":109,"title":108},{"path":89,"title":1384},"フロントエンドガイド",{"path":121,"title":1386},"Go agent — NAS 同期エージェント",{"path":125,"title":1388},"astar CLI",{"path":113,"title":117},{"path":137,"title":136},{"path":141,"title":140},{"path":145,"title":144},{"path":149,"title":148},{"path":153,"title":152},{"path":157,"title":156},{"path":161,"title":160},{"path":165,"title":164},{"path":169,"title":168},{"path":173,"title":172},{"path":177,"title":176},{"path":181,"title":180},{"path":185,"title":184},{"path":189,"title":188},{"path":193,"title":192},{"path":129,"title":1335},{"path":205,"title":204},{"path":209,"title":208},{"path":197,"title":201},{"path":213,"title":1410},"docs/ 地図",1785452455083]