# Directories API

Directories organise your pages into a tree, the way folders organise files. A page's slug says where it lives: `/docs/api/pages` lives in the `/docs/api` directory, which lives in `/docs`. [Pages](/docs/pages/overview#directories) introduces directories alongside pages and sections.

You rarely create a directory yourself. Creating a page creates every directory above it, so creating `/docs/api/pages` gives you `/docs` and `/docs/api` as well.

**A node can be both a page and a directory.** `/blog` can be your blog's index page and also hold `/blog/hello` beneath it. A filesystem would not allow that; here it is a normal shape, and the API is built around it.
## Reading the tree

A `Directory` is one folder in your content tree. Read one to build navigation, such as a documentation sidebar or a site map, or to list everything filed under a path.

```graphql
type Directory implements PageReference & PageNode {
  slug: String!
  path: String!
  title: String                  # Set when the directory is also a page
  hasChildren: Boolean!          # Whether anything sits directly inside it
  children: DirectoryConnection! # The pages and directories directly inside it
  pages: [Page!]!                # The pages directly inside it
  metadata: PageMetadata
  permissions: PagePermissions!
}
```

Three queries reach it:

- **`directories`** returns the directories at the top level.
- **`directory(path: String!)`** returns one directory by its path, or `null`.
- **`pagesNode(ref: SlugOrId!)`** returns whatever is at a slug or ID, page or directory, as a `PageNode`.

Walk down with `children`. Each child is a `PageNode`, the interface pages and directories share, so one selection reads the title and `hasChildren` of every child. Ask for page-only fields with `... on Page`:

```graphql
query {
  directory(path: "/docs") {
    children {
      edges {
        node {
          slug
          title
          hasChildren
          ... on Page {
            id
          }
        }
      }
    }
  }
}
```

Use `hasChildren` to tell a node you can open from a leaf, for example to draw an expand arrow in a sidebar. It is true for a page that has pages beneath it, too.

**A page at the directory's own path is listed first.** If `/blog` is a page as well as a directory, `directory(path: "/blog")` lists the `/blog` page itself at the top of `children` and `pages`, followed by what is inside. That is how an index page shows up alongside its posts. Skip it if you only want what is inside.

Only nodes you can read are listed. A child you have no `read` permission on is left out rather than failing the whole query.
## Creating and deleting
### Create a directory

Create an empty directory with `createDirectory`.

```graphql
mutation {
  createDirectory(path: "/docs/guides") {
    path
  }
}
```

It creates any directories above it too, and needs `write` [permission](/docs/pages/publishing#permissions) where the new directory will live. It is safe to repeat: if the directory already exists, you get it back unchanged.

Create one yourself when you want it to exist before it has any pages.
### Delete a directory

Delete a directory, and optionally everything inside it, with `deleteDirectory`.

```graphql
mutation {
  deleteDirectory(ref: { slug: "/docs/old" }, recursive: false) {
    deleted
    pageCount
    directoryCount
  }
}
```

Without `recursive`, only an empty directory is deleted. If anything is inside, nothing is deleted: `deleted` is `false`, and `pageCount` and `directoryCount` say what is in the way.

With `recursive: true` it deletes the directory and everything beneath it, at any depth, and the counts say what was removed. This cannot be undone.
### Empty a directory and keep it

Start a directory afresh with `clearDirectory`, which keeps the directory and its permissions.

```graphql
mutation {
  clearDirectory(ref: { slug: "/docs/old" }) {
    pageCount
    directoryCount
  }
}
```

`clearDirectory` deletes everything inside a directory but keeps the directory, with its permissions. Use it rather than deleting and recreating a directory whose permissions you want to keep.
### Deleting a page that has pages beneath it

[`deletePage`](/docs/api/pages/pages#delete-page) deletes a page's content, never what is filed beneath it. If anything is beneath it, the node stays as a directory and `deletePage` returns `false`. To remove it and everything under it, use `deleteDirectory` with `recursive: true`.
## Ordering pages

Pages in a directory keep the order you give them. A new page goes at the end. To move one, give its slug and its new position, counting from `0`:

```graphql
mutation {
  movePage(ref: { slug: "/docs/introduction" }, to: { index: 0 }) {
    slug
  }
}
```

`movePage` reorders a page within its own directory. Refer to the page by slug: an ID is not accepted here. To move a page to a different directory, create it at the new slug and delete the old one.
### Previous and next

That order is also what `Page.next` and `Page.previous` follow: the page or directory before and after this one in its directory, or `null` at either end. They are what a "previous / next" footer on a documentation site is built from:

```graphql
query {
  page(ref: { slug: "/docs/introduction" }) {
    previous {
      ... on Page {
        slug
        title
      }
    }
    next {
      ... on Page {
        slug
        title
      }
    }
  }
}
```

Each is a `DirectoryChild`, which is a `Page` or a `Directory`, so select the fields you need on each type.
---

Previous: [Sections API](/docs/api/pages/sections) · Next: [Users API](/docs/api/users/users)
