Welcome back. In our previous lesson, we established the core architectural model of Capacitor, contrasting its "native shell + WebView" approach with your past experiences in Electron and React Native. You now have the high-level "why" and "what" of Capacitor's design.
Today, we'll zoom in on the practical mechanics of how this architecture is implemented on disk. Our goal is to identify the three key components that form the connective tissue between your React SPA and the native mobile world: the capacitor.config.ts file, the web build directory, and the native iOS/Android project folders. Understanding the distinct role of each is fundamental to every command you will run and every configuration you will tweak.
1. The Blueprint: capacitor.config.ts
Every Capacitor project is governed by a central configuration file. While a capacitor.config.json is supported, the modern and recommended approach is to use a TypeScript file, capacitor.config.ts, which provides type safety and the ability to include logic.
This file acts as the primary blueprint for your mobile app. It tells Capacitor essential information, such as its unique identity, its public name, and, most importantly, where to find your compiled web application.
Take a look at this typical Capacitor project structure. You can see the configuration file sitting at the root, alongside the native project folders.

The three most critical properties you will define in this file at the outset are appId, appName, and webDir.
Capacitor Configuration | Capacitor Documentation
The official Capacitor documentation provides the definitive schema for the configuration file. Reading the definitions for these core properties is the best way to understand their precise function.
First, review the example configuration to see how the file is structured. Then, in the Schema section, carefully read the descriptions for the three main properties: appId: This is the unique identifier for your app, equivalent to a Bundle ID on iOS or an Application ID on Android. appName: This is the human-readable name that appears on the home screen. webDir: This tells Capacitor which directory contains your final, compiled web assets.
The appId must be a unique, reverse-domain style string (e.g., com.yourcompany.appname) and is difficult to change once an app is submitted to stores. The appName is what users will see. But for our immediate purposes, webDir is the most important property to understand, as it creates the essential link between your web code and the native shell.
2. The Payload: The Web Build Directory
The webDir property in your config file points to a specific directory. This directory is not where you write your React components; rather, it's the output of your web application's build process. When you run a command like bun run build for your SPA, your build tool (like Vite or Create React App) compiles your TypeScript/JSX code, bundles your JavaScript, and creates a self-contained set of files—typically in a folder named dist or build.
This folder is the "payload." It contains the index.html file, along with all the necessary JS, CSS, and image assets required to run your application. Capacitor treats this directory as a self-contained unit.
This diagram illustrates the flow. The "Web Assets (built web dir)" is precisely the folder we are discussing. This payload can be deployed on its own as a Progressive Web App (PWA), or it can be compiled into a native application, which is our focus.

When you execute Capacitor commands, it looks inside the directory specified by webDir and copies its entire contents into the native projects. The native WebView is then configured to load the index.html from this copied location, effectively booting up your React application inside the native shell.
3. The Containers: Native iOS & Android Projects
After you add the mobile platforms to your Capacitor project, you will see two new directories at your project root: ios and android.
It is crucial to understand that these are not intermediate build artifacts or black boxes. They are complete, first-class native projects:
- The
iosdirectory contains a full Xcode project (.xcworkspace). - The
androiddirectory contains a full Android Studio project (using Gradle).
You can open these projects directly in their respective IDEs. This is where you (or a native developer on your team) would perform platform-specific configuration, edit native code, manage permissions, or debug native-level issues. This is a significant departure from frameworks that try to abstract the native project away from you. Capacitor embraces them.
The connection to your web app is straightforward: when you run a command like cap sync, Capacitor copies the contents of your webDir into a specific asset location within these native projects.
- For iOS, this is typically
ios/App/App/public. - For Android, this is
android/app/src/main/assets/public.
The native shell is pre-configured to load its WebView content from that internal public directory.
To see how this all fits together in a practical workflow, watch this short segment. The host uses npx, which is functionally identical to the bunx command you'll be using.
Create The Most POWERFUL Native Mobile Apps | Capacitor & Javascript
This video by Simon Grimm demonstrates the process of building and syncing a Capacitor app, visually reinforcing the concepts we've discussed.
Watch from this section, where he first runs the web build, then adds the native platforms, and finally explains the sync command. Notice how the android and ios folders appear after running cap add, and how he emphasizes that Capacitor needs the dist folder (the webDir) to exist before it can copy the assets over.
As the video explains, the sync command is the orchestrator. It reads the config, finds the webDir, copies the web assets into the ios and android projects, and updates any native dependencies required by the plugins you've installed.
Conclusion
You've now seen the three pillars of a Capacitor project's structure. Let's summarize their roles:
capacitor.config.ts: The central blueprint. It defines the app's identity and, crucially, tells Capacitor where to find the compiled web assets via thewebDirproperty.- The Web Build Directory: The payload. This is the output of your web app's build process, containing the
index.htmland all other assets needed to run the app. It's the content that will be displayed in the WebView. - The
ios/andandroid/Projects: The containers. These are full-fledged native projects that house your web payload. They serve as the native shell and are the final products that get compiled and submitted to the app stores.
With this mental model of the key files and folders, you are ready to move from identification to creation. In our next lesson, we will install the Capacitor CLI and its core dependencies into your Turborepo workspace and run bunx cap init to generate the capacitor.config.ts file for your project.
Can't find a good explanation? Sign up and we'll make it for you
Sign up