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

# EdgeSpark project structure

> How an EdgeSpark project is organized: server and web apps, repo-authored defs, generated files, auth config, and what never to edit manually.

An EdgeSpark project created with `edgespark init` has a root project plus separate `server/` and `web/` apps. Your repo owns the app schema and bucket declarations in `server/src/defs/`. EdgeSpark generates runtime types and platform-managed schema files in `server/src/__generated__/`.

## Directory layout

<Tree>
  <Folder name="my-app" defaultOpen>
    <Folder name="server" defaultOpen>
      <Folder name="src" defaultOpen>
        <File name="index.ts" />

        <Folder name="defs" defaultOpen>
          <File name="db_schema.ts" />

          <File name="db_relations.ts" />

          <File name="storage_schema.ts" />

          <File name="runtime.ts" />

          <File name="index.ts" />
        </Folder>

        <Folder name="__generated__" defaultOpen>
          <File name="sys_schema.ts" />

          <File name="sys_relations.ts" />

          <File name="edgespark.d.ts" />

          <File name="server-types.d.ts" />
        </Folder>
      </Folder>
    </Folder>

    <Folder name="web">
      <File name="package.json" />

      <Folder name="src">
        <File name="App.tsx" />

        <File name="lib/edgespark.ts" />
      </Folder>
    </Folder>

    <Folder name="configs">
      <File name="auth-config.yaml" />
    </Folder>

    <File name="edgespark.toml" />

    <File name="package.json" />

    <File name="AGENTS.md / CLAUDE.md / GEMINI.md" />
  </Folder>
</Tree>

## Key files

### `server/src/index.ts`

Your server entry point. Define a static Hono app and export it as the default export:

```typescript server/src/index.ts theme={null}
import { db } from "edgespark";
import { auth } from "edgespark/http";
import { Hono } from "hono";
import { posts } from "@defs";

const app = new Hono()
  .get("/api/posts", async (c) => {
    const rows = await db.select().from(posts);
    return c.json(rows);
  })
  .get("/api/me", (c) => {
    return c.json({ email: auth.user.email });
  });

export default app;
```

EdgeSpark requires your server module to default-export the Hono app. Keep the contract explicit with `export default app;`. The variable name can differ, but the module's default export must be the app instance.

You can split routes across multiple files and import them into `server/src/index.ts`. All app routes still need to live under `/api/*`, `/api/public/*`, or `/api/webhooks/*`.

### `server/src/defs/`

Repo-authored definitions. This is where you declare your app schema, storage buckets, and typed runtime keys:

| File                | Contains                                                 |
| ------------------- | -------------------------------------------------------- |
| `db_schema.ts`      | Your Drizzle table definitions                           |
| `db_relations.ts`   | Your Drizzle relations                                   |
| `storage_schema.ts` | Your bucket declarations                                 |
| `runtime.ts`        | `VarKey` and `SecretKey` unions for vars and secrets     |
| `index.ts`          | Required barrel that re-exports defs and generated files |

These are the files you edit. After changing them, use the matching CLI command:

* `edgespark db generate` and `edgespark db migrate` for `db_schema.ts`
* `edgespark storage apply` for `storage_schema.ts`
* `edgespark auth apply` for `configs/auth-config.yaml`

### `server/src/__generated__/`

Generated files from the platform. Do not edit these manually.

| File                | Contains                                              |
| ------------------- | ----------------------------------------------------- |
| `sys_schema.ts`     | Platform-managed database tables                      |
| `sys_relations.ts`  | Relations for platform-managed tables                 |
| `edgespark.d.ts`    | Generated module declarations for `edgespark` imports |
| `server-types.d.ts` | Generated SDK types used by the scaffold and defs     |

Run `edgespark pull` to refresh generated files. `edgespark pull schema` refreshes pulled system schema, and `edgespark pull types` refreshes generated SDK types.

### `edgespark.toml`

Project configuration file created by `edgespark init`. It points EdgeSpark at your server and web directories:

```toml edgespark.toml theme={null}
project_id = "abc123"

[server]
path = "server"

[web]
path = "web"
output_path = "web/dist"
```

Commit this file. The CLI reads it to know which project to deploy and where each part of the scaffold lives.

### `configs/auth-config.yaml`

Local auth configuration file. Use it with `edgespark auth pull` and `edgespark auth apply` when you need to manage sign-in methods and auth settings in code.

### `web/src/lib/edgespark.ts`

The scaffolded browser client entry point. It creates the `@edgespark/web` singleton used for frontend auth, managed auth UI, and same-origin API calls.

### Web import alias

The web scaffold also configures the `@/` alias for `web/src/*`, so imports such as `@/lib/edgespark` and `@/hooks/useAuth` work out of the box.

### Root `package.json`

The root package is intentionally minimal. It is not a workspace. Install dependencies separately in `server/` and `web/`.

## Install dependencies

```bash theme={null}
cd server && npm install
cd ../web && npm install
```

## Organizing routes

As your project grows, split routes into separate files:

<Tree>
  <Folder name="server/src" defaultOpen>
    <File name="index.ts" />

    <Folder name="routes" defaultOpen>
      <File name="posts.ts" />

      <File name="users.ts" />

      <File name="webhooks.ts" />
    </Folder>
  </Folder>
</Tree>

```typescript server/src/index.ts theme={null}
import { auth } from "edgespark/http";
import { Hono } from "hono";
import { postsRoutes } from "./routes/posts";
import { usersRoutes } from "./routes/users";

const app = new Hono()
  .get("/api/me", (c) => c.json({ email: auth.user.email }));

app.route("/api/posts", postsRoutes);
app.route("/api/users", usersRoutes);

export default app;
```

```typescript server/src/routes/posts.ts theme={null}
import { db } from "edgespark";
import { Hono } from "hono";
import { posts } from "@defs";

export const postsRoutes = new Hono().get("/", async (c) => {
  const rows = await db.select().from(posts);
  return c.json(rows);
});
```

## See also

<Columns cols={2}>
  <Card title="The client object" icon="code" href="/concepts/client-object">
    What the runtime SDK provides and how imports from `edgespark` work.
  </Card>

  <Card title="Declarative workflow" icon="database" href="/agents/declarative-workflow">
    How repo-authored defs and generated files stay in sync.
  </Card>

  <Card title="Quickstart" icon="bolt" href="/quickstart">
    Create your first project and deploy it in minutes.
  </Card>

  <Card title="CLI commands" icon="terminal" href="/cli/commands">
    `edgespark init` options and the rest of the public CLI surface.
  </Card>
</Columns>
