# Getting started

Source: https://docx-editor.portone.io/docs/getting-started

Install the package, mount the editor, and export the edited document.

## Install the package [#install-the-package]

```sh
npm i @portone/docx-editor
```

## Import the stylesheet [#import-the-stylesheet]

```ts
import "@portone/docx-editor/styles.css";
```

Once per application; it includes the ProseMirror base styles.
[Styling](https://docx-editor.portone.io/docs/styling.md) covers the custom properties that restyle the frame.

## Get a document to open [#get-a-document-to-open]

`document` takes a `File`, a `Blob`, an `ArrayBuffer`, or a `Uint8Array`:

```ts
const response = await fetch("/agreement.docx");
const file = new File([await response.blob()], "agreement.docx");
```

## Mount the editor [#mount-the-editor]

```tsx
import { DocxEditor, type DocxEditorHandle } from "@portone/docx-editor";
import { useRef } from "react";

export function Editor({ file }: { file: File }) {
  const editorRef = useRef<DocxEditorHandle | null>(null);

  return (
    <DocxEditor
      ref={editorRef}
      document={file}
      mode={{ kind: "edit", author: { id: user.id, name: user.name } }}
    />
  );
}
```

`mode` is a reader's, a commenter's, or an editor's surface, and `author` is the signed-in user
comments are written under; [Props](https://docx-editor.portone.io/docs/props.md#mode) describes the prop and
[Modes](https://docx-editor.portone.io/docs/features/modes.md) what each kind lets a person do.
The editor fills the height it is given, so put it in a box with one.

## Export the edited document [#export-the-edited-document]

`downloadDocx` takes the handle from the ref and saves the current state as a file:

```tsx
import { downloadDocx } from "@portone/docx-editor";

const download = () => {
  const result = downloadDocx(editorRef.current, { fileName: file.name });
  if (result.status === "blocked") {
    console.warn(result.problems.map((problem) => problem.code));
  }
};

<button onClick={download} type="button">
  Export .docx
</button>;
```

It reports `unavailable` while no document is open, `empty` when there is nothing to export, and
`blocked` with the problems when the document cannot be written back safely.
For the bytes without a download, call `editorRef.current.exportBytes()`; for the problems ahead
of it, `editorRef.current.exportProblems()`.

## Check what you see [#check-what-you-see]

An opened document shows its own paper, fonts, and styles, with page boundaries drawn over the
text and the toolbar above it.
If a panel naming a reason appears instead, the document was refused; pass `renderImportError` to
render the refusal yourself, and [Errors](https://docx-editor.portone.io/docs/core/errors.md) lists the codes.
Exporting and reopening the file in Word is the real check.

## Next.js and other prerendering frameworks [#nextjs-and-other-prerendering-frameworks]

The editor cannot render on the server, so load it from a client component through a dynamic
import with server rendering turned off:

```tsx
"use client";

import dynamic from "next/dynamic";

const Editor = dynamic(() => import("./Editor").then((m) => m.Editor), {
  ssr: false,
});
```

Fetch the document inside that client component too.
The App Router also needs `@portone/docx-editor` in `transpilePackages` when it resolves to
TypeScript sources, as a workspace link does.