TypeScript Path Mappings Configuration in the OpenCut Monorepo: A Complete Guide
OpenCut configures TypeScript path mappings in apps/web/tsconfig.json using #/* and @/* aliases that resolve to ./src/*, enabling absolute imports while maintaining compatibility with Vite's bundler resolution strategy.
The OpenCut video editing application is organized as a monorepo managed by Moon, where each application maintains its own TypeScript configuration. Understanding the TypeScript path mappings configuration across the OpenCut codebase reveals how the project achieves clean, absolute imports without complex relative path traversal.
How Path Mappings Are Configured in OpenCut
The primary TypeScript configuration for the web application resides in apps/web/tsconfig.json. This file defines the compiler options that enable modern module resolution while establishing convenient import aliases.
The tsconfig.json Structure
Inside apps/web/tsconfig.json, the compilerOptions section specifies two critical path mappings:
{
"compilerOptions": {
"paths": {
"#/*": ["./src/*"],
"@/*": ["./src/*"]
},
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true
}
}
Both #/* and @/* act as prefix aliases that TypeScript resolves relative to the ./src directory. The moduleResolution strategy is set to "bundler", which aligns TypeScript's path resolution with Vite's native behavior, eliminating the need for duplicate alias configuration in the build tool.
Monorepo Architecture and Path Resolution
OpenCut leverages Moon to orchestrate its monorepo structure, with each project isolated under the apps/ directory. This architecture ensures that path mappings remain scoped to individual applications rather than bleeding across package boundaries.
Moon Workspace Configuration
The root .moon/workspace.yml file defines the monorepo boundaries:
projects:
- apps/*
This configuration instructs Moon to discover projects within the apps directory. Consequently, the TypeScript path mappings in apps/web/tsconfig.json apply exclusively to the web application, preventing cross-project import confusion while maintaining strict project isolation.
Vite Integration
The web application uses Vite as its build tool, configured in apps/web/vite.config.ts. When moduleResolution is set to "bundler" in tsconfig.json, Vite automatically recognizes and resolves the same #/* and @/* aliases during both development and production builds without requiring explicit resolve.alias configuration in the Vite config.
Practical Usage Examples
Developers can import modules using these aliases throughout the web application codebase:
// apps/web/src/routes/index.tsx
import Header from '@/components/Header'
import utils from '#/lib/utils'
These imports resolve to:
@/components/Header→apps/web/src/components/Header.tsx#/lib/utils→apps/web/src/lib/utils.ts
For type-only imports, the aliases work identically:
// apps/web/src/lib/api.ts
import type { User } from '@/types/user'
Why This Configuration Works
The alignment between TypeScript and Vite relies on the moduleResolution: "bundler" setting. This modern resolution strategy allows TypeScript to handle imports with extensions (.ts, .tsx) while matching Vite's native expectations.
The allowImportingTsExtensions and verbatimModuleSyntax options ensure that import statements retain their TypeScript extensions in the source code, which Vite requires for proper dependency graph construction. Because both tools parse tsconfig.json identically, developers experience consistent autocompletion in editors and successful compilation during builds.
Summary
- Path aliases: OpenCut uses
#/*and@/*inapps/web/tsconfig.jsonto map imports to./src/*. - Monorepo structure: Moon manages projects under
apps/*, with each app maintaining isolated TypeScript configurations. - Build tool alignment: Setting
moduleResolutionto"bundler"ensures Vite resolves paths identically to TypeScript without additional configuration. - Extension handling:
allowImportingTsExtensionspreserves.tsand.tsxsuffixes in imports, matching Vite's requirements.
Frequently Asked Questions
What do the #/* and @/* aliases represent in OpenCut?
Both aliases serve identical functions as shorthand for the ./src directory within the web application. They allow developers to write import Component from '@/components/Component' instead of navigating complex relative paths like ../../../components/Component. The dual prefix convention provides flexibility for different organizational preferences while targeting the same source root.
How does Vite resolve TypeScript path mappings without explicit configuration?
Vite automatically reads compilerOptions.paths from tsconfig.json when moduleResolution is set to "bundler". This synchronization means the vite.config.ts file does not require manual resolve.alias entries, reducing configuration duplication and preventing resolution mismatches between the type checker and the bundler.
Can I use these path aliases in other apps within the OpenCut monorepo?
Each application within the apps/ directory maintains its own tsconfig.json file. While the web app at apps/web defines these specific aliases, other applications would need their own paths configuration in their respective tsconfig.json files. Moon's workspace isolation ensures that TypeScript settings do not leak between projects, so aliases must be configured per-app.
What is the purpose of moduleResolution: "bundler" in this configuration?
This setting enables TypeScript to resolve modules using the same algorithm as modern bundlers like Vite. It allows the use of extensioned imports (.ts, .tsx) and supports the paths mapping without requiring baseUrl configuration. For OpenCut, this ensures perfect alignment between compile-time type checking and runtime module resolution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →