> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Architecture Skeleton

export const Link = ({href, children, className, ...props}) => {
  const localizedHref = href;
  return <a href={localizedHref} className={className} {...props}>
      {children}
    </a>;
};

export const MultiRelatedLinks = ({sections = []}) => {
  if (!sections || sections.length === 0) {
    return null;
  }
  return <div className="space-y-8">
      {sections.map((section, index) => <RelatedLinks key={index} title={section.title} items={section.items} />)}
    </div>;
};

export const RelatedLinks = ({title, items = []}) => {
  const getBadgeClass = badge => {
    if (!badge) return "badge-default";
    const badgeType = badge.toLowerCase().replace(/\s+/g, "-");
    return `badge-${badge === "ガイド" ? "guide" : badgeType}`;
  };
  if (!items || items.length === 0) {
    return null;
  }
  return <div className="my-8">
      {}
      <h3 className="text-sm font-bold uppercase tracking-wider mb-4">{title}</h3>

      {}
      <div className="flex flex-col gap-3">
        {items.map((item, index) => <a key={index} href={item.href} className="py-2 px-3 rounded related_link hover:bg-[#f2f2f2] dark:hover:bg-[#111827] flex items-center gap-3 group no-underline hover:no-underline border-b-0">
            {}
            <span className={`px-2 py-1 rounded-full text-xs font-semibold uppercase tracking-wide flex-shrink-0 ${getBadgeClass(item.badge)}`}>
              {item.badge}
            </span>

            {}
            <span className="text-base">{item.label}</span>
          </a>)}
      </div>
    </div>;
};

Our first requirement is to copy general files and folders into each individual
user's root folder on account creation. This problem has been solved within
standard Linux distributions through a directory called `/etc/skel`,
which we'll emulate with a Box specific solution here. When adding a new user in
Linux, the files and folders within `/etc/skel` are copied to the new user's
home directory.

When creating a
<Link href="/guides/authentication/jwt/jwt-setup">JWT-based Box application</Link>, a
<Link href="/platform/user-types/#service-account">Service Account</Link> is created
within the Box Enterprise. A Service Account is similar in functionality to a
co-admin within a Box Enterprise, and most useful to this use case, can own,
copy, and collaborate other users on files and folders. More importantly, you
don't have to use a Service Account strictly for developing platform applications
for users, and instead, can use a Service Account in more of an automation
capacity.

<Info>
  **Box Platform Application Requirements**

  When creating your JWT-based custom Box application for this recipe, you'll
  need to enable the following scopes: **Manage users**, **Manage groups**,
  **Perform Actions as Users**, and **Generate User Access Tokens**.

  See <Link href="/guides/authentication/jwt/jwt-setup">JWT Application Setup</Link> for
  more information on creating a JWT-based Box application and the scopes in a
  Box application.
</Info>

We'll start by creating the `etc` and `skel` folders and granting ownership of
the folders to the Service Account.

<Tabs>
  <Tab title="etc_skel.json">
    ```json theme={null}
    {
      "name": "etc",
      "parent": {
        "id": "0"
      },
      "children": [
        {
          "name": "skel",
          "children": []
        }
      ]
    }
    ```
  </Tab>

  <Tab title="skel_sub_directories.json">
    ```json theme={null}
    [
      {
        "name": "Market Research",
        "parent": {
          "id": "44884797174"
        },
        "children": [
          {
            "name": "Statistics",
            "children": [
              {
                "name": "Computed",
                "children": []
              }
            ]
          }
        ]
      },
      {
        "name": "Sales Plays",
        "parent": {
          "id": "44884797174"
        },
        "children": [
          {
            "name": "Big Pharma",
            "children": []
          }
        ]
      }
    ]
    ```
  </Tab>
</Tabs>

The code here can optionally be reused to build any folder structure formatted
as the JSON objects above demonstrate.

<Tabs>
  <Tab title="Node">
    ```js theme={null}
    "use strict";
    const fs = require("fs");
    const box = require("box-node-sdk");

    class BoxFolderTreeCreator {
        constructor(boxClient, options) {
            options = options || {};
            if (options.boxClient) {
                throw new Error("Must include a boxClient field.");
            }

            options.boxFolderTreeName = options.boxFolderTreeName || "tree.json";

            this.boxClient = boxClient;
            this.boxFolderTree = JSON.parse(fs.readFileSync(options.boxFolderTreeName));
            this.createdBoxFolders = [];
        }

        async createFolderTree(branch = null, parentFolderId = "0") {
            this.createdBoxFolders = [];
            if (Array.isArray(this.boxFolderTree)) {
                let folderTasks = [];
                this.boxFolderTree.forEach(folder => {
                    folderTasks.push(this._createFolder(folder, ""));
                });
                await Promise.all(folderTasks);
                return this.createdBoxFolders;
            } else if (typeof this.boxFolderTree === "object") {
                console.log("Is object");
                await this._createFolders(this.boxFolderTree, "");
                return this.createdBoxFolders;
            } else {
                throw new Error("Incorrectly formatted JSON folder tree.");
            }
        }

        async _createFolders(branch, parentFolderId = "0") {
            if (branch.parent != null && branch.parent.id != null) {
                parentFolderId = branch.parent.id;
            }
            let folder;
            try {
                folder = await this.boxClient.folders.create(parentFolderId, branch.name);
            } catch (e) {
                let existingFolderId = BoxFolderTreeCreator.handleFolderConflictError(e);
                folder = await this.boxClient.folders.get(existingFolderId);
            }
            this.createdBoxFolders.push(folder);
            if (branch.children.length <= 0) {
                console.log("No more folders to create...");
                return;
            } else {
                let createFolderTasks = [];
                branch.children.forEach(child => {
                    console.log("Creating folder...");
                    console.log(child.name);
                    createFolderTasks.push(this._createFolders(child, folder.id));
                });
                return await Promise.all(createFolderTasks);
            }
        }

        static handleFolderConflictError(e) {
            if (e && e.response && e.response.body) {
                let errorBody = e.response.body;
                if (errorBody.status === 409) {
                    if (
                        errorBody.context_info &&
                        errorBody.context_info.conflicts &&
                        errorBody.context_info.conflicts.length > 0
                    ) {
                        let conflict = errorBody.context_info.conflicts[0];
                        if (conflict && conflict.id) {
                            return conflict.id;
                        }
                    }
                }
            }
        }
    }

    let configFile = fs.readFileSync("config.json");
    configFile = JSON.parse(configFile);

    let session = box.getPreconfiguredInstance(configFile);
    let serviceAccountClient = session.getAppAuthClient("enterprise");

    let treeCreator = new BoxFolderTreeCreator(serviceAccountClient);

    (async () => {
        let createdFolders = await treeCreator.createFolderTree();
        console.log(createdFolders);
    })();
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    package com.box;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    import com.box.sdk.BoxAPIException;
    import com.box.sdk.BoxConfig;
    import com.box.sdk.BoxDeveloperEditionAPIConnection;
    import com.box.sdk.BoxFolder;
    import com.eclipsesource.json.JsonObject;
    import com.eclipsesource.json.JsonValue;

    public class BoxFolderTreeCreator {
        private BoxDeveloperEditionAPIConnection _boxClient;
        private JsonValue _boxFolderTree;
        private ArrayList<BoxFolder.Info > _createdFolders;

        public BoxFolderTreeCreator(BoxDeveloperEditionAPIConnection
            boxClient) throws IOException {
            this(boxClient, "tree.json");
        }

        public BoxFolderTreeCreator(BoxDeveloperEditionAPIConnection boxClient,
            String folderTreeFileName)
        throws IOException {
            this._boxClient = boxClient;
            try (BufferedReader tree =
                Files.newBufferedReader(Paths.get(folderTreeFileName))) {
                this._boxFolderTree = JsonValue.readFrom(tree);
            }
            this._createdFolders = new ArrayList<>();
        }

        public ArrayList<BoxFolder.Info > createFolderTree() {
            if (this._boxFolderTree.isArray()) {
                for (JsonValue folder: this._boxFolderTree.asArray()) {
                    System.out.println("Processing this folder: " + folder);
                    _createFolders(folder.asObject(), null);
                }
                return this._createdFolders;
            } else {
                _createFolders(this._boxFolderTree.asObject(), null);
                return this._createdFolders;
            }
        }

        private void _createFolders(JsonObject branch, String parentFolderID) {
            if (parentFolderID == null && branch.get("parent") != null &&
                branch.get("parent").asObject().get("id") != null) {
                System.out.println("Looking for parent folder id...");
                System.out.println(branch.get("parent").asObject().get("id").asString());
                parentFolderID = branch.get("parent").asObject().get("id").asString();
            }
            System.out.println("Folder name:");
            System.out.println(branch.get("name"));
            System.out.println("Parent Folder ID:");
            System.out.println(parentFolderID);
            BoxFolder.Info createdFolder;
            try {
                BoxFolder parent = new BoxFolder(this._boxClient, parentFolderID);
                createdFolder = parent.createFolder(branch.get("name").asString());
            } catch (BoxAPIException e) {
                if (e.getResponseCode() == 409) {
                    // Use the ID returned from the conflict error to continue
                    String conflictId = getIdFromConflict(e.getResponse());
                    createdFolder = new BoxFolder(this._boxClient, conflictId).getInfo();
                } else {
                    throw e;
                }
            }

            this._createdFolders.add(createdFolder);

            if (!branch.get("children").asArray().isEmpty()) {
                for (JsonValue child: branch.get("children").asArray()) {
                    _createFolders(child.asObject(), createdFolder.getID());
                }
            } else {
                return;
            }
        }

        private static String getIdFromConflict(String message) {
            String id = "";
            Pattern p = Pattern.compile("\"id\":\"[0-9]+\"");
            Pattern p2 = Pattern.compile("[0-9]+");
            Matcher m = p.matcher(message);
            if (m.find()) {
                String sub = m.group();
                Matcher m2 = p2.matcher(sub);
                if (m2.find()) {
                    id = m2.group();
                }
            }
            return id;
        }

        public static void main(String[] args) throws Exception {
            Path configPath = Paths.get("config.json");
            try (BufferedReader reader =
                Files.newBufferedReader(configPath, Charset.forName("UTF-8"))) {
                BoxConfig boxConfig = BoxConfig.readFrom(reader);
                BoxDeveloperEditionAPIConnection serviceAccountClient = BoxDeveloperEditionAPIConnection
                    .getAppEnterpriseConnection(boxConfig);

                BoxFolderTreeCreator treeBuilder = new
                    BoxFolderTreeCreator(serviceAccountClient, "etc_skel.json");
                ArrayList<BoxFolder.Info > folders = treeBuilder.createFolderTree();
                for (BoxFolder.Info folder: folders) {
                    System.out.println(folder.getID());
                }
            }
        }
    }
    ```
  </Tab>

  <Tab title=".NET">
    ```csharp theme={null}
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Box.V2;
    using Box.V2.Config;
    using Box.V2.Exceptions;
    using Box.V2.JWTAuth;
    using Box.V2.Models;
    using Newtonsoft.Json.Linq;

    namespace BoxPlayground {
        public class Program {
            static void Main(string[] args) {
                ExecuteMainAsync().Wait();
            }

            private static async Task ExecuteMainAsync() {
                using(FileStream fs = new FileStream("./config.json",
                    FileMode.Open)) {
                    var session = new BoxJWTAuth(BoxConfig.CreateFromJsonFile(fs));
                    var client = session.AdminClient(session.AdminToken());
                    var treeCreator = new BoxFolderTreeCreator(client, "etc_skel.json");
                    var createdFolders = await treeCreator.CreateFolderTree();
                    foreach(var folder in createdFolders) {
                        System.Console.WriteLine(folder.Name);
                        System.Console.WriteLine(folder.Id);
                    }

                }
            }

            public class BoxFolderTreeCreator {
                public BoxClient BoxClient {
                    get;
                    set;
                }
                public JToken BoxFolderTree {
                    get;
                    set;
                }
                public List < BoxFolder > CreatedBoxFolders {
                    get;
                    set;
                }

                public BoxFolderTreeCreator(BoxClient boxClient,
                    string boxFolderTreeFileName = "tree.json") {
                    this.BoxClient = boxClient;
                    this.BoxFolderTree = JToken.Parse(File.ReadAllText(boxFolderTreeFileName));
                    this.CreatedBoxFolders = new List < BoxFolder > ();
                }
                public async Task < List < BoxFolder >>
                    CreateFolderTree(dynamic branch = null,
                    string parentFolderId = "0") {
                    this.CreatedBoxFolders = new List < BoxFolder > ();

                    if (this.BoxFolderTree is JArray) {
                        var folderTasks = new List < Task > ();
                        foreach(JObject folder in this.BoxFolderTree) {
                            folderTasks.Add(_createFolder(folder, String.Empty));
                        }
                        await Task.WhenAll(folderTasks);
                        return this.CreatedBoxFolders;
                    }
                    else if (this.BoxFolderTree is JObject) {
                        System.Console.WriteLine("Is object");
                        await _createFolder(this.BoxFolderTree as JObject, String.Empty);
                        return this.CreatedBoxFolders;
                    }
                    else {
                        throw new Exception("Incorrectly formatted JSON folder tree.");
                    }

                }

                private async Task _createFolder(dynamic branch,
                    string parentFolderId = "0") {

                    if (branch.parent != null && branch.parent.id != null) {
                        parentFolderId = branch.parent.id;
                    }

                    BoxFolder createdFolder;
                    try {
                        createdFolder = await this.BoxClient.FoldersManager.CreateAsync(
                            new BoxFolderRequest {
                                Parent = new BoxRequestEntity {
                                    Id = parentFolderId
                                },
                                Name = branch.name
                        });
                    }
                    catch(BoxConflictException < BoxFolder > e) {
                        createdFolder = await this.BoxClient.FoldersManager.GetInformationAsync(e.ConflictingItems.FirstOrDefault().Id);
                    }

                    this.CreatedBoxFolders.Add(createdFolder);

                    if (branch.children.Count <= 0) {
                        System.Console.WriteLine("No more folders to create...");
                        return;
                    }
                    else {
                        var createFolderTasks = new List < Task > ();
                        foreach(var child in branch.children) {
                            System.Console.WriteLine("Creating folder...");
                            System.Console.WriteLine(child.name);
                            createFolderTasks.Add(_createFolder(child as JObject,
                                createdFolder.Id));
                        }
                        await Task.WhenAll(createFolderTasks);
                    }
                }
            }
        }
    }
    ```
  </Tab>
</Tabs>

<RelatedLinks
  title="RELATED GUIDES"
  items={[
{ label: translate("Populate Content"), href: "/guides/users/provision/populate-content", badge: "GUIDE" }
]}
/>
