{
+ constructor(props: ErrorBoundaryProps) {
+ super(props)
+
+ // Define a state variable to track whether is an error or not
+ this.state = { hasError: false }
+ }
+ static getDerivedStateFromError(error: any) {
+ // Update state so the next render will show the fallback UI
+
+ return { hasError: true }
+ }
+ componentDidCatch(error: any, errorInfo: any) {
+ // You can use your own error logging service here
+ console.log({ error, errorInfo })
+ }
+ render() {
+ // Check if the error is thrown
+ if (this.state.hasError) {
+ // You can render any custom fallback UI
+ // return (
+ //
+ //
Oops, there is an error!
+ //
+ //
+ // )
+ }
+
+ // Return children components in case of no error
+ return this.props.children
+ }
+}
+
+export default ErrorBoundary
diff --git a/apps/book-web/src/components/ErrorBoundary/index.tsx b/apps/book-web/src/components/ErrorBoundary/index.tsx
new file mode 100644
index 00000000..0f76c913
--- /dev/null
+++ b/apps/book-web/src/components/ErrorBoundary/index.tsx
@@ -0,0 +1 @@
+export { default } from './ErrorBoundary.jsx'
diff --git a/packages/velog-web/src/components/Layouts/BasicLayout/BasicLayout.module.css b/apps/book-web/src/components/MarkdownRender/MarkdownRender.module.css
similarity index 100%
rename from packages/velog-web/src/components/Layouts/BasicLayout/BasicLayout.module.css
rename to apps/book-web/src/components/MarkdownRender/MarkdownRender.module.css
diff --git a/packages/velog-web/src/components/MarkdownRender/MarkdownRender.test.tsx b/apps/book-web/src/components/MarkdownRender/MarkdownRender.test.tsx
similarity index 100%
rename from packages/velog-web/src/components/MarkdownRender/MarkdownRender.test.tsx
rename to apps/book-web/src/components/MarkdownRender/MarkdownRender.test.tsx
diff --git a/apps/book-web/src/components/MarkdownRender/MarkdownRender.tsx b/apps/book-web/src/components/MarkdownRender/MarkdownRender.tsx
new file mode 100644
index 00000000..f75d6fb8
--- /dev/null
+++ b/apps/book-web/src/components/MarkdownRender/MarkdownRender.tsx
@@ -0,0 +1,7 @@
+'use client'
+
+function MarkdownRender() {
+ return
+}
+
+export default MarkdownRender
diff --git a/apps/book-web/src/components/MarkdownRender/index.tsx b/apps/book-web/src/components/MarkdownRender/index.tsx
new file mode 100644
index 00000000..bcc4470a
--- /dev/null
+++ b/apps/book-web/src/components/MarkdownRender/index.tsx
@@ -0,0 +1 @@
+export { default } from './MarkdownRender.jsx'
diff --git a/apps/book-web/src/env.ts b/apps/book-web/src/env.ts
new file mode 100644
index 00000000..13fa725e
--- /dev/null
+++ b/apps/book-web/src/env.ts
@@ -0,0 +1,28 @@
+import { z } from 'zod'
+
+type DockerEnv = 'development' | 'stage' | 'production'
+type AppEnvironment = 'development' | 'production'
+
+const dockerEnv = (process.env.DOCKER_ENV as DockerEnv) || 'development'
+const appEnv: AppEnvironment = ['stage', 'production'].includes(dockerEnv)
+ ? 'production'
+ : 'development'
+
+const env = z.object({
+ dockerEnv: z.enum(['development', 'production', 'stage']),
+ appEnv: z.enum(['development', 'production']),
+ publicUrl: z.string(),
+ clientHost: z.string(),
+ graphqlServerHost: z.string(),
+ graphqlBookServerHost: z.string(),
+})
+
+export const ENV = env.parse({
+ dockerEnv,
+ // allowed standard env names, https://nextjs.org/docs/messages/non-standard-node-env
+ appEnv,
+ publicUrl: process.env.NEXT_PUBLIC_PUBLIC_URL,
+ clientHost: process.env.NEXT_PUBLIC_CLIENT_HOST,
+ graphqlServerHost: process.env.NEXT_PUBLIC_GRAPHQL_SERVER_HOST,
+ graphqlBookServerHost: process.env.NEXT_PUBLIC_GRAPHQL_BOOK_SERVER_HOST,
+})
diff --git a/packages/velog-web/src/components/MarkdownEditor/MarkdownEditor.module.css b/apps/book-web/src/features/edit/components/Body/Body.module.css
similarity index 100%
rename from packages/velog-web/src/components/MarkdownEditor/MarkdownEditor.module.css
rename to apps/book-web/src/features/edit/components/Body/Body.module.css
diff --git a/apps/book-web/src/features/edit/components/Body/Body.test.tsx b/apps/book-web/src/features/edit/components/Body/Body.test.tsx
new file mode 100644
index 00000000..506eb549
--- /dev/null
+++ b/apps/book-web/src/features/edit/components/Body/Body.test.tsx
@@ -0,0 +1,8 @@
+import Body from './Body'
+import { render } from '@testing-library/react'
+
+describe('Body', () => {
+ it('renders successfully', () => {
+ render()
+ })
+})
diff --git a/apps/book-web/src/features/edit/components/Body/Body.tsx b/apps/book-web/src/features/edit/components/Body/Body.tsx
new file mode 100644
index 00000000..5771c3dd
--- /dev/null
+++ b/apps/book-web/src/features/edit/components/Body/Body.tsx
@@ -0,0 +1,7 @@
+'use client'
+
+function Body() {
+ return