Applicable Scenarios
Use this skill when the user mentions the following requirements:
- Create HarmonyOS NEXT empty project / empty project / minimal runnable project
- Quickly generate a runnable shell project for examples (such as maps, SDK demos, etc.)
- Create a standard HarmonyOS NEXT minimal project from scratch in the current repository
This skill guides the agent tocreate from scratcha standard minimal runnable project structure for HarmonyOS NEXT based on the Stage model + ArkTS.
Project Structure Reference (Minimal Runnable Project)
When creating a HarmonyOS NEXT empty project from scratch, it is recommended to use the following general structure (with {ProjectName} as a placeholder):
{ProjectName}/oh-package.json5build-profile.json5hvigorfile.tshvigor/hvigor-config.json5
AppScope/app.json5resources/...
entry/oh-package.json5build-profile.json5hvigorfile.tssrc/main/module.json5src/main/ets/entryability/EntryAbility.etssrc/main/ets/entrybackupability/EntryBackupAbility.ets(Optional)src/main/ets/pages/Index.etssrc/main/resources/...
The above structure is the recommended layout for a minimal runnable HarmonyOS NEXT application project.
Quick Usage Process (Creating an Empty Project for the User)
When the user requests to "create a standard HarmonyOS empty project / HarmonyOS NEXT minimal project", follow the steps below.
Step 1: Confirm Target Information
Infer from the user context or confirm with the user (if necessary):
- Target project directory name (for example:
harmony-demo,harmony-map-demo) - Application bundle name (such as:
com.example.demoapp) - Application display name (such as:
DemoApp)
Project bundle name generation rules:
- If the userexplicitly provides a bundle name(such as
com.example.mapdemo), thenstrictly use the bundle name specified by the user, and do not automatically rewrite or append a suffix. - If the userdoes not specify a bundle name, thenprefer to automatically generate a bundle name based on the application theme / business scenario, for example:
- When the theme is "Map Demo", you can generate
com.example.mapdemo - When the theme is "Health Record", you can generate
com.example.healthrecord
- When the theme is "Map Demo", you can generate
- Only when a clear theme cannot be inferred from the context should you fall back to a generic placeholder bundle name (as shown below).
If the user does not explicitly specify, use reasonable defaults:
- Directory name:
harmony-demo - Bundle name: by default, generate a semantic bundle name based on the application theme; if the theme cannot be identified, use
com.example.harmonydemo - Application name:
Harmony Demo
Step 2: Create the Project Directory and Basic Files
- Create the project root directory under the current working directory, for example:
{ProjectName}/(such asharmony-demo/)
- Under
{ProjectName}/, create the following files and directories:oh-package.json5: containsmodelVersion、description、dependencies、devDependenciesand other basic fields, for example:modelVersion:"6.0.0"devDependenciescan include@ohos/hypium、@ohos/hamockto support testing- Dependency writing rules: Once a third-party or system dependency (such as a map library, network library, etc.) is used in the project, the corresponding dependency must be explicitly written into the
oh-package.json5of the appropriate level ofdependenciesfield, rather than only being directly used in codeimport。
build-profile.json5: defines the app-level product and build modes (products、buildModeSet, etc.),targetSdkVersion、compatibleSdkVersionmust match the development environmenthvigorfile.ts: importappTasksand export the default configuration:system: appTasksplugins: []
hvigor/hvigor-config.json5: Hvigor global configuration file; if missing, it will cause a build error similar to "Hvigor config file .../hvigor/hvigor-config.json5 does not exist"AppScope/app.json5: definesbundleName、vendor、versionCode、versionName、icon、label, etc.AppScope/resources/: contains at least the basic string and icon resources (placeholder resources can be generated by the agent according to the minimal configuration); if usinglayered_imageas the app icon, you must provide underAppScope/resources/base/media/bothlayered_image.jsonand thebackground、foregroundmedia file it references (such asbackground.svg、foreground.svg), otherwise resource package error 11211120 will be reported.
- Under
{ProjectName}/entry/, create the module directory and the following files:oh-package.json5: the package configuration file of the entry module itself (independent of the root directoryoh-package.json5, used to avoid DevEco / build tool errors "Missing file "oh-package.json5" in entry").When a dependency is used only in the entry module, the dependency should preferably be written into the entry module'soh-package.json5'sdependencies.build-profile.json5: defines the entry module build configurationhvigorfile.ts: importshapTasksand exports the default configuration:system: hapTasksplugins: []
src/main/module.json5: defines the module name, type,mainElement、deviceTypes、pages、abilities, etc.src/main/ets/entryability/EntryAbility.etsandsrc/main/ets/pages/Index.ets: contains the minimal UI and ability entry codesrc/main/resources/: contains the resource JSON for strings, float values, colors, etc. referenced by the pages
Dependency management and installation rules
- Dependency declaration location:
- Any ohpm dependency used in the project (for example
@bdmap/base、@bdmap/map, etc.) must be written into thespecific modulethat actually uses the dependency, in itsoh-package.json5'sdependenciesfield (if only entry uses it, write it into{ProjectName}/entry/oh-package.json5)。 - If the dependency is shared by multiple modules of the entire application, it can be written into the project root directory
oh-package.json5according to the actual situation, but it must still be ensured that the build of the module using it can resolve the dependency.
- Any ohpm dependency used in the project (for example
- Attempt to install dependencies:
- When creating or modifying a project for the user, the agent should attempt to execute
{ProjectName}/) in the corresponding project directory (usuallyohpm install) to actually install the dependencies declared inoh-package.json5. - If the runtime environment does not support actually executing the installation command, the response should clearly instruct the user to manually execute
ohpm installor the corresponding installation command in the project directory, and ensure that the dependency list inoh-package.json5is complete and correct.
- When creating or modifying a project for the user, the agent should attempt to execute
Step 3: Modify basic application information
In the new project directory (for example {ProjectName}/), set or modify the configuration according to the following key points:
-
Application scope information:
AppScope/app.json5- Path:
{ProjectName}/AppScope/app.json5 - Fields:
bundleName: set to the target package name (such ascom.example.harmonydemo)label: usually references a string resource (such as$string:app_name), and can remain unchanged if neededversionCode/versionName: adjust accordingly if the user requests a specific version number
- Path:
-
If needed, adjust the project name and product information:
build-profile.json5- Path:
{ProjectName}/build-profile.json5 - Usually the default can be kept; if the user has requirements for the product name, etc., fine-tune it in
products.
- Path:
Step 4: Confirm the module configuration is complete
In the new project directory, check whether the following key files exist and are structurally complete (usually only confirmation is needed, no modification):
-
{ProjectName}/oh-package.json5modelVersionfield exists, for example"6.0.0"- If you need to use a testing framework,
devDependenciescontains@ohos/hypiumand other dependencies
-
{ProjectName}/entry/src/main/module.json5module.nameis"entry"mainElementpoints to"EntryAbility"pagespoints to$profile:main_pagesabilities[0].srcEntrypoints to./ets/entryability/EntryAbility.ets
-
{ProjectName}/hvigorfile.tsand{ProjectName}/entry/hvigorfile.ts- Use at the top level
appTasks, and the entry module useshapTasks
- Use at the top level
Step 5: Adjust the home page (optional)
If the user wants to customize a simple home page (rather than just the default Hello World), you can modify:
- Path:
{ProjectName}/entry/src/main/ets/pages/Index.ets
Keep the structure as a @Entry + @Component component, with the inner build() returning a basic layout (such as RelativeContainer or Column) and a Text text, ensuring the page structure is simple and compilable.
Feasibility self-check (verification points when the agent executes)
After creating the new empty project directory for the user, the agent should perform the following self-check to verify the feasibility of the structure:
-
Structure check
- Must exist:
{ProjectName}/oh-package.json5{ProjectName}/build-profile.json5{ProjectName}/hvigorfile.ts{ProjectName}/hvigor/hvigor-config.json5{ProjectName}/AppScope/app.json5{ProjectName}/entry/oh-package.json5{ProjectName}/entry/hvigorfile.ts{ProjectName}/entry/src/main/module.json5{ProjectName}/entry/src/main/ets/pages/Index.ets
- If these files are missing, the agent should create the missing files or report to the user that the current structure is incomplete.
- Must exist:
-
Configuration consistency check
AppScope/app.json5inbundleNameis consistent with the user's target package name.entry/src/main/module.json5InmainElementthe ability pointed to actually exists in theabilitieslist.abilities[0].srcEntrythe.etsfile pointed to actually exists.
-
Pre-build check (Auto Run recommended)
- If the HarmonyOS NEXT build toolchain is already installed in the environment,it is recommended to configure the Hvigor build command as part of the auto run process: after the new project is created or the template is modified, automatically run
hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemonin the new project directory (or the equivalent build command provided by DevEco Studio), and confirm that there are no obvious structural errors. - For scenarios that continue development based on this empty project, it is recommended to configure a pre-commit or CI auto run script at the repository level to uniformly execute the above build command, ensuring that any changes based on this template can pass basic compilation checks.
- If the build tool is unavailable, then use compliance of the structure with the requirements of "Project Structure Reference" and "Feasibility Self-check" in this skill as the criterion for judging "feasible", and indicate in the documentation or response that the user needs to manually execute
hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemonafter having the toolchain locally to complete the final verification.
- If the HarmonyOS NEXT build toolchain is already installed in the environment,it is recommended to configure the Hvigor build command as part of the auto run process: after the new project is created or the template is modified, automatically run
Resource package and media resource constraints (required reading)
To avoid build errors Error Code: 11211120, Resource Pack Error: The resource reference '$media:xxx' is not defined, the following constraints must be observed when creating or copying an empty project:
-
layered_image and references must exist in pairs
layered_image.jsonreferenced in$media:background、$media:foregroundindicates thatin the same directorythere must exist a media file namedbackground、foreground(such asbackground.svg、foreground.svg)。- If in AppScope you use
icon: "$media:layered_image"(seeAppScope/app.json5), then you must place both underAppScope/resources/base/media/:layered_image.jsonbackground.svg(orbackground.png, svg recommended)foreground.svg(orforeground.png, svg recommended)
- If in entry module is used
icon: "$media:layered_image"(seeentry/src/main/module.json5), then the above three items must likewise be placed underentry/src/main/resources/base/media/(or at leastbackground、foregroundtwo media files +layered_image.json)。 - Copying only
layered_image.jsonwithout copying or creatingbackground、foregroundmedia files will cause a 11211120 error.
-
Other $media references
- Any
$media:资源名appearing in the configuration (such as$media:startIcon) must have a file with the same name under theresources/base/media/of the corresponding module (such asstartIcon.svg), otherwise a resource pack error will likewise be triggered. $media:资源名The resolution ofthe project itselfresource directory (such asentry/src/main/resources/base/media/、AppScope/resources/base/media/) only occurs in.cursor/skills/..., and will not be read from skill directories such as
- Any
-
Requirements for agents when creating an empty project
- When using this skill template to create a new project, for any directory involving
layered_image.json, thebackground、foregroundmedia files that need to be placed must also be generated or specified (it is recommended to use a minimal usable svg placeholder image), and it is not allowed to create onlylayered_image.json。 - Icons should uniformly use svg: App/ability icon-related media resources (including but not limited to
layered_imageofbackground/foreground、startWindowIconofstartIcon) should preferentially generate svg format files. - Generation priority rules: Preferentially automatically generate an svg matching the scenario based on the user's app scenario (app name/theme/business type, such as maps, travel, tools, etc.); if generation fails or the user does not provide any scenario information, then copy one from the sample source code provided in this skill documentcopy oneas a fallback placeholder resource (and still write it under the project's
resources/base/media/).
- When using this skill template to create a new project, for any directory involving
For more details, see HarmonyOS resource tool restool。
Reference template code
This section uses the standard minimal executable sample project provided in the repository as the blueprint, and provides the template code and configuration for a minimal executable project. When generating files, the agent shouldremain consistent with this(only replacing identifiers such as directory name/package name), and ensure that media resources such as icons use svg rather than png.
1. Root directory oh-package.json5
```json
{
"modelVersion": "6.0.0",
"description": "Please describe the basic information.",
"dependencies": {
},
"devDependencies": {
"@ohos/hypium": "1.0.24",
"@ohos/hamock": "1.0.0"
}
}
### 2. 根目录 `build-profile.json5`
```markdown
```json
{
"app": {
"signingConfigs": [],
"products": [
{
"name": "default",
"signingConfig": "default",
"targetSdkVersion": "6.0.0(20)",
"compatibleSdkVersion": "5.0.4(16)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
"buildModeSet": [
{
"name": "debug",
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}
### 3. 根目录 `hvigorfile.ts`
```markdown
```ts
import { appTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}
### 4. 根目录 `hvigor/hvigor-config.json5`
```markdown
```json5
{
"modelVersion": "6.0.0",
"dependencies": {
},
"execution": {
// "analyze": "normal",
// "daemon": true,
// "incremental": true,
// "parallel": true,
// "typeCheck": false,
// "optimizationStrategy": "memory"
},
"logging": {
// "level": "info"
},
"debugging": {
// "stacktrace": false
},
"nodeOptions": {
// "maxOldSpaceSize": 8192,
// "exposeGC": true
}
}
### 5. `AppScope/app.json5`
```markdown
```json
{
"app": {
"bundleName": "com.example.application",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:layered_image",
"label": "$string:app_name"
}
}
### 6. `AppScope/resources/base/element/string.json`
```markdown
```json
{
"string": [
{
"name": "app_name",
"value": "Harmony Demo"
}
]
}
### 7. `AppScope/resources/base/media/layered_image.json`
```markdown
```json
{
"layered-image": {
"background": "$media:background",
"foreground": "$media:foreground"
}
}
> **约束**:`$media:background`、`$media:foreground` 必须在**同目录** `AppScope/resources/base/media/` 下存在对应文件(如 `background.svg`、`foreground.svg`),否则构建报错 11211120。详见上文「资源包与媒体资源约束」。推荐使用 svg,勿仅创建本 JSON 而不创建 background/foreground 文件。
### 8. entry 模块 `oh-package.json5`
```markdown
```json
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {}
}
### 9. entry 模块 `build-profile.json5`
```markdown
```json5
{
"apiType": "stageMode",
"buildOption": {
"resOptions": {
"copyCodeResource": {
"enable": false
}
}
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}
### 10. entry 模块 `hvigorfile.ts`
```markdown
```ts
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}
### 11. entry 模块 `src/main/module.json5`
```markdown
```json5
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
}
### 12. `EntryAbility.ets`(入口能力)
```markdown
```ts
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
}
### 13. `EntryBackupAbility.ets`(备份扩展能力)
```markdown
```ts
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
const DOMAIN = 0x0000;
export default class EntryBackupAbility extends BackupExtensionAbility {
async onBackup() {
hilog.info(DOMAIN, 'testTag', 'onBackup ok');
await Promise.resolve();
}
async onRestore(bundleVersion: BundleVersion) {
hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
await Promise.resolve();
}
}
### 14. `pages/Index.ets`(首页页面)
```markdown
```ts
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
})
}
.height('100%')
.width('100%')
}
}
### 15. entry 关键资源示例
- `entry/src/main/resources/base/element/string.json`
```markdown
```json
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}
- `entry/src/main/resources/base/element/float.json`
```markdown
```json
{
"float": [
{
"name": "page_text_font_size",
"value": "50fp"
}
]
}
- `entry/src/main/resources/base/element/color.json`
```markdown
```json
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}
- `entry/src/main/resources/base/profile/main_pages.json`
```markdown
```json
{
"src": [
"pages/Index"
]
}
- `entry/src/main/resources/base/profile/backup_config.json`
```markdown
```json
{
"allowToBackupRestore": true
}
- `entry/src/main/resources/base/media/layered_image.json`
```markdown
```json
{
"layered-image": {
"background": "$media:background",
"foreground": "$media:foreground"
}
}
> **约束**:entry 的 `resources/base/media/` 下也须存在 `background.svg`、`foreground.svg`(或同名 png),否则 11211120。详见「资源包与媒体资源约束」。
- `entry/src/main/resources/base/media/startIcon.svg`
```markdown
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 108" width="108" height="108">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#2F7DFF"/>
<stop offset="100%" stop-color="#0A59F7"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="108" height="108" rx="24" fill="url(#bg)"/>
<rect x="28" y="28" width="22" height="22" rx="6" fill="#EAF1FF"/>
<rect x="58" y="28" width="22" height="22" rx="6" fill="#DDE9FF"/>
<rect x="28" y="58" width="22" height="22" rx="6" fill="#DDE9FF"/>
<rect x="58" y="58" width="22" height="22" rx="6" fill="#BFD6FF"/>
</svg>
> **约束**:若 `entry/src/main/module.json5` 中存在 `"startWindowIcon": "$media:startIcon"`,则 entry 的 `resources/base/media/` 下必须存在 `startIcon.svg`(或 `startIcon.png`),并且**文件名大小写需与 `$media:` 引用一致**(受 `caseSensitiveCheck` 影响)。
代理在创建空工程时,应直接以本节模板为基础生成文件,并根据用户给定的 `{ProjectName}`、`bundleName` 等做相应替换,且在引入媒体资源时统一采用 svg 格式。
---
## 使用示例
### 示例一:创建默认空工程
用户:
> @harmony 帮我创建一个 HarmonyOS NEXT 的空工程,用来做后续 SDK Demo。
代理应当:
1. 按“快速使用流程”在当前目录下创建 `{ProjectName}`(如 `harmony-demo`)工程结构。
2. 将包名设置为 `com.example.harmonydemo`。
### 示例二:创建带自定义包名的空工程
用户:
> 基于现在这个最小工程结构,帮我再创建一个包名为 `com.example.mapdemo` 的鸿蒙空工程。
代理应当:
1. 在当前目录下创建 `{ProjectName}`(如 `harmony-map-demo`)工程结构。
2. 在新工程中修改:
- `{ProjectName}/AppScope/app.json5` 中的 `bundleName` 为 `com.example.mapdemo`。
3. 按“可行性自检”章节检查关键文件与字段。
---
## 总结
- 本技能基于当前仓库自带的 `harmony` 最小可运行示例工程,通过**结构复制 + 少量配置修改**,快速为用户创建 HarmonyOS NEXT 标准空工程。
- 代理在执行时应始终对照模板工程结构进行检查,确保新工程在文件布局与关键配置上与模板保持一致,从而保证可行性。