diff --git a/package.json b/package.json
index c39f84b6..31eceae5 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "fs": "INTEGRATION=filesystem npm run dev",
     "code": "INTEGRATION=code npm run dev",
     "diff-viewer": "INTEGRATION=diff-viewer npm run dev",
+    "provider": "INTEGRATION=provider npm run dev",
     "build": "node scripts/build",
     "build:all": "yarn run bundle && yarn run generate && yarn run build",
     "bundle": "node scripts/bundle",
diff --git a/packages/core/src/api/exports.ts b/packages/core/src/api/exports.ts
index b94f3b76..90582a0e 100644
--- a/packages/core/src/api/exports.ts
+++ b/packages/core/src/api/exports.ts
@@ -4,6 +4,8 @@ export { Emitter, Uri } from '@opensumi/ide-core-common';
 
 export { getDefaultLayoutConfig } from '../core/layout';
 
+export { CodeEditor } from '../core/components/CodeEditor'
+
 export { BrowserFSFileType, HOME_ROOT, REPORT_NAME, WORKSPACE_ROOT };
 
 export * from '../core/env';
diff --git a/packages/core/src/api/renderApp.tsx b/packages/core/src/api/renderApp.tsx
index 57560276..132e0c0b 100644
--- a/packages/core/src/api/renderApp.tsx
+++ b/packages/core/src/api/renderApp.tsx
@@ -1,7 +1,7 @@
 import { REPORT_NAME, RuntimeConfig } from '@codeblitzjs/ide-sumi-core';
 import { getDebugLogger, IReporterService, localize } from '@opensumi/ide-core-common';
 import cls from 'classnames';
-import React, { CSSProperties, useEffect, useMemo, useRef, useState } from 'react';
+import React, { CSSProperties, useEffect, useMemo, useRef, useState, Fragment } from 'react';
 import { createRoot } from 'react-dom/client';
 import { useConstant } from '../core/hooks';
 import { IPropsService, PropsServiceImpl } from '../core/props.service';
@@ -10,6 +10,7 @@ import styles from '../core/style.module.less';
 import { LandingProps, RootProps } from '../core/types';
 import { createApp } from './createApp';
 import { IAppInstance, IConfig } from './types';
+import { AppContext } from '../core/components/context'
 
 export interface IAppRendererProps extends IConfig {
   onLoad?(app: IAppInstance): void;
@@ -132,3 +133,69 @@ export const AppRenderer: React.FC<IAppRendererProps> = ({ onLoad, Landing, ...o
     </Root>
   );
 };
+
+export const AppProvider: React.FC<React.PropsWithChildren<IAppRendererProps>> = ({ onLoad, children, ...opts }) => {
+  const app = useConstant(() => {
+    opts.appConfig.layoutComponent = () => <Fragment></Fragment>
+    return createApp(opts)
+  });
+  const [clientApp, setClientApp] = useState<IAppInstance | null>(null);
+  const appElementRef = useRef<React.FC | null>(null);
+  const propsService = useConstant(() => new PropsServiceImpl<IAppRendererProps>());
+  propsService.props = opts;
+
+  const runtimeConfig: RuntimeConfig = app.injector.get(RuntimeConfig);
+  runtimeConfig.workspace = opts.runtimeConfig.workspace;
+
+  const [state, setState] = useState<{
+    status: RootProps['status'];
+    error?: RootProps['error'];
+  }>(() => ({ status: 'pending' }));
+
+  useMemo(() => {
+    app.injector.addProviders({
+      token: IPropsService,
+      useValue: propsService,
+    });
+  }, []);
+
+  useEffect(() => {
+    app
+      .start((appElement) => {
+        appElementRef.current = appElement;
+        setClientApp(app)
+        setState({ status: 'success' });
+        return Promise.resolve();
+      })
+      .then(() => {
+        onLoad?.(app);
+      })
+      .catch((err: Error) => {
+        setState({ error: err?.message || localize('error.unknown'), status: 'error' });
+
+        (app.injector.get(IReporterService) as IReporterService).point(
+          REPORT_NAME.APP_START_ERROR,
+          err?.message,
+          {
+            error: err,
+          },
+        );
+        getDebugLogger().error(err);
+        setTimeout(() => {
+          throw err;
+        });
+      });
+
+    return () => {
+      app.destroy();
+    };
+  }, []);
+
+  const contextValue = useMemo(() => ({ app: clientApp }), [clientApp])
+
+  return (
+    <AppContext.Provider value={contextValue}>
+      {children}
+    </AppContext.Provider>
+  )
+};
diff --git a/packages/core/src/core/components/CodeEditor.tsx b/packages/core/src/core/components/CodeEditor.tsx
new file mode 100644
index 00000000..3c36ed86
--- /dev/null
+++ b/packages/core/src/core/components/CodeEditor.tsx
@@ -0,0 +1,95 @@
+import React, { useContext, useEffect, useMemo, useRef, useCallback } from 'react';
+
+import * as path from 'path'
+import { URI, useInjectable } from '@opensumi/ide-core-browser';
+import { ConfigProvider, AppConfig } from '@opensumi/ide-core-browser/lib/react-providers/config-provider'
+import { EditorCollectionService, ICodeEditor, IEditorDocumentModelRef } from '@opensumi/ide-editor/lib/common'
+import { IEditorDocumentModelService } from '@opensumi/ide-editor/lib/browser/doc-model/types'
+import { AppContext } from './context'
+
+const noop = () => {}
+
+export function useMemorizeFn<T extends (...args: any[]) => any>(fn: T) {
+  const fnRef = useRef<T>(fn);
+  fnRef.current = useMemo(() => fn, [fn]);
+  return useCallback((...args: any) => fnRef.current(...args), []) as T;
+}
+
+export interface ICodeEditorProps extends React.HTMLAttributes<HTMLDivElement> {
+  uri: URI | string;
+
+  editorOptions?: any;
+
+  onEditorCreate?: (editor: ICodeEditor) => void;
+}
+
+export const CodeEditorComponent = ({ uri, editorOptions, onEditorCreate, ...props }: ICodeEditorProps) => {
+  const editorCollectionService: EditorCollectionService = useInjectable(EditorCollectionService);
+  const documentService: IEditorDocumentModelService = useInjectable(IEditorDocumentModelService);
+  const appConfig: AppConfig = useInjectable(AppConfig);
+
+  const containerRef = React.useRef<HTMLDivElement | null>(null);
+  const uriStr = useMemo(() => {
+    if (typeof uri === 'string') {
+      return URI.file(path.join(appConfig.workspaceDir, uri)).toString()
+    }
+    return uri.toString()
+  }, [uri])
+  const fetchingUriRef = useRef<string>('');
+  const documentModelRef = useRef<IEditorDocumentModelRef>();
+  const editorRef = useRef<ICodeEditor>()
+  const unmountRef = useRef(false);
+  const onEditorCreateMemorizeFn = useMemorizeFn(onEditorCreate || noop)
+
+  const openDocumentModel = () => {
+    if (editorRef.current && documentModelRef.current) {
+      editorRef.current.open(documentModelRef.current)
+    }
+  }
+
+  React.useEffect(() => {
+    if (containerRef.current) {
+      editorRef.current?.dispose();
+      editorRef.current = editorCollectionService.createCodeEditor(containerRef.current, {
+        automaticLayout: true,
+        ...editorOptions,
+      });
+      onEditorCreateMemorizeFn(editorRef.current)
+      openDocumentModel()
+    }
+    return () => {
+      unmountRef.current = true;
+      editorRef.current?.dispose()
+      documentModelRef.current?.dispose()
+    };
+  }, []);
+
+  useEffect(() => {
+    if (fetchingUriRef.current !== uriStr) {
+      fetchingUriRef.current = uriStr
+      documentService.createModelReference(new URI(uriStr), 'editor-react-component').then((ref) => {
+        if (documentModelRef.current) {
+          documentModelRef.current.dispose();
+        }
+        if (!unmountRef.current && ref.instance.uri.toString() === uriStr) {
+          documentModelRef.current = ref;
+          openDocumentModel()
+        } else {
+          ref.dispose();
+        }
+      });
+    }
+  }, [uriStr])
+
+  return <div ref={containerRef} {...props}></div>;
+};
+
+export const CodeEditor = (props: ICodeEditorProps) => {
+  const appContext = useContext(AppContext)
+  if (!appContext.app) return null
+  return (
+    <ConfigProvider value={appContext.app.config}>
+      <CodeEditorComponent {...props} />
+    </ConfigProvider>
+  )
+};
diff --git a/packages/core/src/core/components/context.ts b/packages/core/src/core/components/context.ts
new file mode 100644
index 00000000..6058e21b
--- /dev/null
+++ b/packages/core/src/core/components/context.ts
@@ -0,0 +1,4 @@
+import { createContext } from 'react'
+import { ClientApp } from '@codeblitzjs/ide-sumi-core'
+
+export const AppContext = createContext<{ app: ClientApp | null }>({ app: null })
diff --git a/packages/core/src/core/types.ts b/packages/core/src/core/types.ts
index 9c695177..cd925817 100644
--- a/packages/core/src/core/types.ts
+++ b/packages/core/src/core/types.ts
@@ -2,7 +2,7 @@ import { ThemeType } from '@opensumi/ide-theme';
 import { ComponentType } from 'react';
 
 export interface LandingProps {
-  status: 'loading' | 'success' | 'error';
+  status: 'loading' | 'success' | 'error' | 'pending';
   error?: string;
   theme?: ThemeType;
   className?: string;
diff --git a/packages/startup/src/provider/index.css b/packages/startup/src/provider/index.css
new file mode 100644
index 00000000..cb7c0940
--- /dev/null
+++ b/packages/startup/src/provider/index.css
@@ -0,0 +1,3 @@
+#main {
+  overflow: auto;
+}
\ No newline at end of file
diff --git a/packages/startup/src/provider/index.tsx b/packages/startup/src/provider/index.tsx
new file mode 100644
index 00000000..c49e3690
--- /dev/null
+++ b/packages/startup/src/provider/index.tsx
@@ -0,0 +1,45 @@
+import { AppProvider, CodeEditor } from '@codeblitzjs/ide-core';
+import React from 'react';
+import { createRoot } from 'react-dom/client';
+import '@codeblitzjs/ide-core/languages';
+import '../index.css';
+import './index.css'
+
+const App = () => (
+  <AppProvider
+    appConfig={{
+      workspaceDir: 'my-workspace',
+      layoutConfig: {},
+    }}
+    runtimeConfig={{
+      biz: 'startup',
+      workspace: {
+        filesystem: {
+          fs: 'FileIndexSystem',
+          options: {
+            // 初始全量文件索引
+            requestFileIndex() {
+              return Promise.resolve({
+                'main.html': '<div id="root"></div>',
+                'main.css': 'body {}',
+                'main.js': 'console.log("main")',
+                'package.json': '{\n  "name": "startup"\n}',
+              });
+            },
+          },
+        }
+      },
+    }}
+  >
+    <CodeEditor
+      uri="main.js"
+      style={{ width: 1000, height: 300, marginBottom: 16 }}
+    />
+    <CodeEditor
+      uri="main.css"
+      style={{ width: 1000, height: 300 }}
+    />
+  </AppProvider>
+);
+
+createRoot(document.getElementById('main') as HTMLElement).render(<App />);
