chore: update npm package name
diff --git a/README.md b/README.md
index f6a059b..4b1f680 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@
 npm run create <series-name>
 ```
 
-The generated files are in `custom-series/<series-name>`.
+The generated files are in `custom-series/<series-name>`. Note that if there are multiple words in the series name, they should be in camel case like `npm run create barRange`.
 
 ## Build
 
diff --git a/custom-series/barRange/package.json b/custom-series/barRange/package.json
index 2d41349..ba26967 100644
--- a/custom-series/barRange/package.json
+++ b/custom-series/barRange/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "echarts-barRange",
+  "name": "@echarts/custom-bar-range",
   "version": "0.0.1",
   "description": "",
   "main": "dist/index.js",
@@ -15,4 +15,4 @@
   "devDependencies": {
     "typescript": "^5.5.4"
   }
-}
\ No newline at end of file
+}
diff --git a/custom-series/violin/package.json b/custom-series/violin/package.json
index c856d37..e1131c8 100644
--- a/custom-series/violin/package.json
+++ b/custom-series/violin/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "echarts-violin",
+  "name": "@echarts/custom-violin",
   "version": "0.0.1-beta",
   "description": "",
   "main": "dist/index.js",
diff --git a/package-lock.json b/package-lock.json
index f385c3b..0dca759 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
       "name": "echarts-custom-series",
       "version": "1.0.0",
       "license": "Apache-2.0",
+      "dependencies": {
+        "chalk": "^4.1.2"
+      },
       "devDependencies": {
         "chokidar": "^3.6.0",
         "http-server": "^14.1.1",
@@ -304,7 +307,6 @@
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
       "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
       "dependencies": {
         "color-convert": "^2.0.1"
       },
@@ -402,7 +404,6 @@
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
       "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
       "dependencies": {
         "ansi-styles": "^4.1.0",
         "supports-color": "^7.1.0"
@@ -442,7 +443,6 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
       "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
       "dependencies": {
         "color-name": "~1.1.4"
       },
@@ -453,8 +453,7 @@
     "node_modules/color-name": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "node_modules/commander": {
       "version": "2.20.3",
@@ -626,7 +625,6 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
       "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
@@ -1040,7 +1038,6 @@
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
       "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
       "dependencies": {
         "has-flag": "^4.0.0"
       },
diff --git a/package.json b/package.json
index 712954d..ad27c02 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,9 @@
   "description": "Custom Series for Apache ECharts",
   "scripts": {
     "build": "node scripts/build.js",
-    "create": "node scripts/create.js",
-    "serve": "node scripts/serve.js"
+    "generate": "node scripts/generate.js",
+    "serve": "node scripts/serve.js",
+    "g": "npm run generate"
   },
   "repository": {
     "type": "git",
@@ -23,5 +24,8 @@
     "rollup": "^4.21.2",
     "terser": "^5.31.6",
     "typescript": "^5.5.4"
+  },
+  "dependencies": {
+    "chalk": "^4.1.2"
   }
 }
diff --git a/scripts/build.js b/scripts/build.js
index a48f682..de0dbd6 100644
--- a/scripts/build.js
+++ b/scripts/build.js
@@ -20,6 +20,7 @@
 const fs = require('fs');
 const path = require('path');
 const { execSync } = require('child_process');
+const chalk = require('chalk');
 
 /**
  * Install dependencies before build if needed.
@@ -31,7 +32,9 @@
   const seriesPath = path.join(__dirname, '../custom-series', dirName);
   const nodeModulesPath = path.join(seriesPath, 'node_modules');
   if (!fs.existsSync(nodeModulesPath)) {
-    console.log(`Installing dependencies for custom series ${dirName}...`);
+    console.log(
+      chalk.gray(`Installing dependencies for custom series ${dirName}...`)
+    );
     execSync(`npm install`, { cwd: seriesPath });
   }
 }
@@ -44,10 +47,11 @@
 function buildCustomSeries(dirName) {
   const seriesPath = path.join(__dirname, '../custom-series', dirName);
   if (fs.statSync(seriesPath).isDirectory() === false) {
+    console.log(chalk.yellow(`${dirName} is not a directory. Ignored.`));
     return;
   }
   if (!fs.existsSync(seriesPath)) {
-    console.error(`Custom series ${dirName} does not exist`);
+    console.error(chalk.red(`Custom series ${dirName} does not exist`));
     return;
   }
 
@@ -91,7 +95,9 @@
     // as long as `lib/index.js` exists
   }
   if (!fs.existsSync(path.join(seriesPath, 'lib/index.js'))) {
-    console.error(`Error compiling TypeScript for custom series ${dirName}:`);
+    console.error(
+      chalk.red(`Error compiling TypeScript for custom series ${dirName}:`)
+    );
     console.error(e);
     process.exit(1);
   }
@@ -118,7 +124,6 @@
     );
 
     console.log(`Rollup bundling completed for ${dirName}`);
-    console.log(result);
 
     // Check if the output file was created
     if (!fs.existsSync(path.join(seriesPath, 'dist', 'index.js'))) {
@@ -159,14 +164,17 @@
   const args = process.argv.slice(2);
   if (args.length === 0) {
     // Build all custom series
-    fs.readdirSync(path.join(__dirname, '../custom-series')).forEach(
-      buildCustomSeries
-    );
+    const dirs = fs.readdirSync(path.join(__dirname, '../custom-series'));
+    dirs.forEach((name, index) => {
+      console.log(chalk.cyan(`Running ${name}: (${index + 1}/${dirs.length})`));
+      buildCustomSeries(name);
+      console.log(`---------------\n`);
+    });
   } else {
     // Build custom series from args
     args.forEach(buildCustomSeries);
   }
-  console.log('Build successfully.');
+  console.log(chalk.green('Build successfully.'));
 }
 
 build();
diff --git a/scripts/create.js b/scripts/generate.js
similarity index 61%
rename from scripts/create.js
rename to scripts/generate.js
index dbf079d..b840024 100644
--- a/scripts/create.js
+++ b/scripts/generate.js
@@ -19,6 +19,7 @@
 
 const fs = require('fs');
 const path = require('path');
+const chalk = require('chalk');
 
 /**
  * Create a new custom series based on template
@@ -28,41 +29,57 @@
   const templatePath = path.join(__dirname, './template');
   const seriesPath = path.join(__dirname, '../custom-series', name);
   if (fs.existsSync(seriesPath)) {
-    console.error(`Custom series ${name} already exists`);
+    console.error(chalk.red(`Custom series ${name} already exists`));
     return;
   }
 
+  // Check if the name is in camelCase, ignore if is not
+  if (!/^[a-z][a-zA-Z0-9]*$/.test(name)) {
+    console.error(
+      chalk.red(
+        `Custom series name must be in camelCase. For example: mySeries`
+      )
+    );
+    process.exit(1);
+  }
+
   fs.mkdirSync(seriesPath);
   copyDirectory(templatePath, seriesPath);
 
   // Replace `$CUSTOM_SERIES_NAME$` in all files under seriesPath with <name>
-  replaceCustomSeriesName(seriesPath, name);
+  const kebabCaseName = toKebabCase(name);
+  replaceCustomSeriesName(seriesPath, name, kebabCaseName);
 
   const packageJsonPath = path.join(seriesPath, 'package.json');
   const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
-  packageJson.name = `echarts-${name}`;
+  packageJson.name = `@echarts/custom-${kebabCaseName}`;
   fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
 
   // Run `npm install`
-  console.log(`Installing dependencies for custom series ${name}...`);
-  require('child_process').execSync(`npm install`, { cwd: seriesPath });
+  console.log(
+    chalk.gray(`Installing dependencies for custom series ${name}...`)
+  );
+  // require('child_process').execSync(`npm install`, { cwd: seriesPath });
 
-  console.log(`Custom series ${name} created successfully`);
-  console.log(`Run "npm run build ${name}" to build the custom series`);
+  console.log(chalk.green(`Custom series ${name} created successfully.\n`));
 }
 
 /**
  * Recursively replace the custom series name in the file
  */
-function replaceCustomSeriesName(filePath, name) {
+function replaceCustomSeriesName(filePath, name, kebabCaseName) {
   if (fs.statSync(filePath).isDirectory()) {
     const items = fs.readdirSync(filePath);
     items.forEach((item) => {
-      replaceCustomSeriesName(path.join(filePath, item), name);
+      replaceCustomSeriesName(path.join(filePath, item), name, kebabCaseName);
     });
   } else {
     const content = fs.readFileSync(filePath, 'utf-8');
-    const newContent = content.replace(/\$CUSTOM_SERIES_NAME\$/g, name);
+    let newContent = content.replace(/\$CUSTOM_SERIES_NAME\$/g, name);
+    newContent = newContent.replace(
+      /\$CUSTOM_SERIES_KEBAB_NAME\$/g,
+      kebabCaseName
+    );
     fs.writeFileSync(filePath, newContent);
   }
 }
@@ -70,7 +87,7 @@
 function copyDirectory(src, dest) {
   // Check if source directory exists
   if (!fs.existsSync(src)) {
-    console.error(`Source directory "${src}" does not exist.`);
+    console.error(chalk.red(`Source directory "${src}" does not exist.`));
     return;
   }
 
@@ -98,11 +115,31 @@
   });
 }
 
+/**
+ * Convert from camelCase to kebab-case
+ */
+function toKebabCase(name) {
+  return name.replace(/([A-Z])/g, '-$1').toLowerCase();
+}
+
 const names = process.argv.slice(2);
 if (names.length === 0) {
   console.error(
-    'Please specify the name of the custom series. For example: npm run create my-series'
+    chalk.red(
+      'Please specify the name of the custom series. For example: npm run create mySeries'
+    )
   );
 } else {
   names.forEach(create);
 }
+
+console.log(
+  chalk.yellow(
+    `Note: before the official release of ECharts v6, you need to clone the "apache/echarts" repo and build it locally, and then use "npm run link echarts" to link the local echarts to the custom series`
+  )
+);
+console.log(
+  chalk.cyan(
+    `Run "npm run serve <custom-series-name>" to start the local development server`
+  )
+);
diff --git a/scripts/serve.js b/scripts/serve.js
index f9c309b..19ecdd4 100644
--- a/scripts/serve.js
+++ b/scripts/serve.js
@@ -21,22 +21,51 @@
 const fs = require('fs');
 const { exec } = require('child_process');
 const chokidar = require('chokidar');
+const chalk = require('chalk');
 
 /**
  * Start a local server to run the test cases.
  */
-function serve() {
+function buildAndServe() {
   const args = process.argv.slice(2);
   if (args.length === 0) {
     console.error(
-      'No custom series name provided. Run `npm run serve <series-name>` to serve a custom series.'
+      chalk.red(
+        'No custom series name provided. Run `npm run serve <series-name>` to serve a custom series.'
+      )
     );
     return;
   }
 
+  console.log('Building...');
+  build().then(() => {
+    startServer();
+  });
+}
+
+function build() {
+  const args = process.argv.slice(2);
+  return new Promise((resolve) => {
+    exec(`npm run build ${args[0]}`, (error, stdout, stderr) => {
+      if (error) {
+        console.error(chalk.red(`Build error: ${error}`));
+        // End the process
+        process.exit(1);
+      }
+      console.log(`Build output: ${stdout}`);
+      if (stderr) {
+        console.error(`Build stderr: ${stderr}`);
+      }
+      resolve();
+    });
+  });
+}
+
+function startServer() {
+  const args = process.argv.slice(2);
   const seriesPath = path.join(__dirname, '../custom-series', args[0]);
   if (!fs.existsSync(seriesPath)) {
-    console.error(`Custom series ${args[0]} does not exist`);
+    console.error(chalk.red(`Custom series ${args[0]} does not exist`));
     return;
   }
 
@@ -48,19 +77,9 @@
     ignored: /(^|[\/\\])\../, // ignore dotfiles
     persistent: true,
   });
-
   watcher.on('change', (path) => {
-    console.log(`File ${path} has been changed. Rebuilding...`);
-    exec(`npm run build ${args[0]}`, (error, stdout, stderr) => {
-      if (error) {
-        console.error(`Build error: ${error}`);
-        return;
-      }
-      console.log(`Build output: ${stdout}`);
-      if (stderr) {
-        console.error(`Build stderr: ${stderr}`);
-      }
-    });
+    console.log(chalk.gray(`File ${path} has been changed. Rebuilding...`));
+    build();
   });
 
   serverProcess.stdout.on('data', (data) => {
@@ -74,19 +93,19 @@
       const url = `http://localhost:${port}/test/index.html`;
       exec(`${open} ${url}`, (error) => {
         if (error) {
-          console.error(`Failed to open browser: ${error}`);
+          console.error(chalk.red(`Failed to open browser: ${error}`));
         }
       });
     }
   });
 
   serverProcess.stderr.on('data', (data) => {
-    console.error(data.toString());
+    console.error(chalk.red(data.toString()));
   });
 
   serverProcess.on('close', (code) => {
-    console.log(`http-server process exited with code ${code}`);
+    console.log(chalk.gray(`http-server process exited with code ${code}`));
   });
 }
 
-serve();
+buildAndServe();
diff --git a/scripts/template/README.md b/scripts/template/README.md
new file mode 100644
index 0000000..1657fa8
--- /dev/null
+++ b/scripts/template/README.md
@@ -0,0 +1,28 @@
+# $CUSTOM_SERIES_NAME$
+
+## Usage
+
+Import the custom series JavaScript file and ECharts, then use `echarts.use` to install it.
+
+```html
+<script src="./node_modules/echarts/dist/echarts.js"></script>
+<script src="./dist/index.js"></script>
+<script>
+  echarts.use(window.$CUSTOM_SERIES_NAME$CustomSeriesInstaller);
+  const chart = echarts.init(...);
+  // ...
+</script>
+```
+
+Or, if using module bundler, install the package from npm and import it.
+
+```bash
+npm install @echarts/custom-$CUSTOM_SERIES_KEBAB_NAME$
+```
+
+```js
+import echarts from 'echarts';
+import $CUSTOM_SERIES_NAME$CustomSeriesInstaller from '@echarts/custom-$CUSTOM_SERIES_KEBAB_NAME$';
+
+echarts.use($CUSTOM_SERIES_NAME$CustomSeriesInstaller);
+```
diff --git a/scripts/template/package.json b/scripts/template/package.json
index 6001e14..0f5343e 100644
--- a/scripts/template/package.json
+++ b/scripts/template/package.json
@@ -1,6 +1,6 @@
 {
-  "name": "echarts-template",
-  "version": "0.0.1",
+  "name": "@echarts/custom-template",
+  "version": "0.0.1-beta.1",
   "description": "",
   "main": "dist/index.js",
   "scripts": {