Project Detection
The @xtarterize/core package provides the detectProject() function - the foundation of xtarterize’s context-aware behavior. It analyzes your project directory to build a ProjectProfile that drives which conformance tasks are applicable.
detectProject() now acts as an orchestration layer in packages/core/src/detect.ts, while concrete detection adapters live in packages/core/src/detect/ (framework, bundler, router, styling, package manager, and monorepo).
Overview
Section titled “Overview”Project detection is the first step in every xtarterize command. It analyzes your project directory to build a ProjectProfile that drives which conformance tasks are applicable.
Profile caching
Section titled “Profile caching”Detection results are cached to avoid redundant I/O on repeated invocations. The cache is stored in .xtarterize/cache/profile-fingerprint.json and keyed by a fingerprint of package.json, lockfile, and config directories (.github/, .vscode/, .changeset/).
The cache is invalidated when any of these inputs change (mtime or size). Corrupt or missing cache files fall through to full re-computation - the cache is always best-effort. A cache hit typically completes in under 1ms vs 50-150ms for a full detection run.
See the file docs/ADRs/xtarterize/021-fingerprint-profile-caching.md for the full design. The .xtarterize/ directory is now automatically gitignored via ADR 026 (replacing the manual approach outlined in ADR 021).
detectProject Function
Section titled “detectProject Function”import { detectProject } from '@xtarterize/core'
const profile = await detectProject('/path/to/project')ProjectProfile Schema
Section titled “ProjectProfile Schema”The detection returns a ProjectProfile object:
interface ProjectProfile { // Framework framework: 'react' | 'react-native' | 'vue' | 'svelte' | 'solid' | 'node' | null frameworkVersion: string | null
// Bundler bundler: 'vite' | 'nextjs' | 'tanstack-start' | 'expo' | 'webpack' | 'rspack' | 'none' | null
// Router router: 'tanstack-router' | 'react-router' | 'next' | 'expo-router' | 'vue-router' | null
// Styling styling: ('tailwind' | 'css-modules' | 'styled-components' | 'vanilla-extract' | 'nativewind' | 'vanilla')[]
// Language & Runtime typescript: boolean runtime: 'browser' | 'node' | 'edge' | 'native' | 'universal'
// Package manager packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun'
// Repo structure monorepo: boolean monorepoTool: 'turbo' | 'nx' | 'lerna' | null workspaceRoot: boolean
// Git hasGitHub: boolean hasGit: boolean
// Existing config presence existing: { biome: boolean tsconfig: boolean renovate: boolean commitlint: boolean knip: boolean plop: boolean turbo: boolean vscodeSettings: boolean agentsMd: boolean githubWorkflows: string[] viteConfig: boolean versionrc: boolean gitignore: boolean }}The workspaceRoot field is set to true when the current directory
itself contains monorepo markers (pnpm-workspace.yaml, turbo.json,
etc.). It is false when running from inside a workspace package
discovered via parent-directory walk-up. In non-monorepos,
workspaceRoot has the same value as monorepo.
Detection Logic
Section titled “Detection Logic”Detection modules
Section titled “Detection modules”framework.ts- framework/runtime/vite-plus detectionbundler.ts- bundler detection from deps and config filesrouter.ts- router detection from bundler + depsstyling.ts- styling solution detectionpackage-manager.ts- lockfile/nypm package manager detectionmonorepo.ts- workspace/monorepo detectiontypes.ts+utils.ts- shared detection types and guards
flowchart TD
A[package.json] --> B{Dependencies}
B --> C[detectFramework]
B --> D[detectBundler]
B --> E[detectRouter]
B --> F[detectStyling]
B --> G[detectVitePlus]
C --> H{Framework?}
H -->|"react-native + react"| I["Ambiguous → prompt user"]
H -->|react| J["Framework: react"]
H -->|vue| K["Framework: vue"]
H -->|svelte| L["Framework: svelte"]
H -->|solid| M["Framework: solid"]
H -->|node| N["Framework: node"]
D --> O{Bundler?}
O -->|"@tanstack/start"| P["TanStack Start"]
O -->|next| Q["Next.js"]
O -->|expo| R["Expo"]
O -->|vite| S["Vite"]
O -->|webpack| T["Webpack"]
O -->|"@rspack/core"| U["Rspack"]
O -->|none| V["None"]
E --> W{Router?}
W -->|"nextjs bundler"| X["Next Router"]
W -->|"expo bundler"| Y["Expo Router"]
W -->|"@tanstack/react-router"| Z["TanStack Router"]
W -->|react-router| AA["React Router"]
W -->|vue-router| AB["Vue Router"]
style A fill:#6366f1,color:#fff
style C fill:#22c55e,color:#fff
style D fill:#22c55e,color:#fff
Detection Sources
Section titled “Detection Sources”| Signal | Source |
|---|---|
| Framework | package.json dependencies (react, vue, react-native, etc.) |
| Bundler | vite, next, expo, webpack, @rspack/core in deps |
| Router | @tanstack/react-router, react-router-dom, vue-router in deps |
| Styling | tailwindcss, styled-components, nativewind in deps |
| Signal | Source |
|---|---|
| TypeScript | tsconfig.json existence, typescript in deps |
| Package manager | Lockfile presence (pnpm-lock.yaml, yarn.lock, etc.) |
| Monorepo | pnpm-workspace.yaml, turbo.json, packages/ + apps/ dirs |
| GitHub | .github/ directory presence |
Ambiguity Handling
Section titled “Ambiguity Handling”Example
Section titled “Example”const profile = await detectProject('/path/to/project')
if (profile.bundler === 'vite' && profile.typescript) { // Vite plugin tasks will be applicable}
if (profile.monorepo && profile.monorepoTool === 'turbo') { // Turbo task may be skip if already configured}References
Section titled “References”- npm package.json Documentation - Package manifest format
- React - UI library for web and native apps
- Vue.js - Progressive JavaScript framework
- React Native - Native app development with React
- Vite - Next-generation frontend build tool
- Next.js - React framework for production
- TanStack Router - Type-safe routing for React
- React Router - Declarative routing for React
- Vue Router - Official router for Vue.js
- Expo - React Native framework
- Webpack - Module bundler
- Rspack - Fast Rust-based web bundler
- Tailwind CSS - Utility-first CSS framework
- Styled Components - CSS-in-JS for React
- NativeWind - Tailwind CSS for React Native
- pnpm Workspaces - Monorepo workspace support
- Turborepo - Monorepo task runner
- TypeScript tsconfig - Compiler configuration