Skip to content

Commit 0980ad1

Browse files
committed
docs(projects): explain project and workspace creation flows
1 parent 91cba23 commit 0980ad1

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

‎apps/sim/lib/projects/README.md‎

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Project creation
2+
3+
A Project groups environments. An environment is an existing `workspace` record; there is no separate environment table. Every newly created Project starts with an environment.
4+
5+
## Choose the creation flow
6+
7+
| Caller | Flow | Result |
8+
| --- | --- | --- |
9+
| New Project onboarding | `POST /api/projects` | Creates a Project and its first environment together, with independently supplied names. |
10+
| Existing workspace creation UI or caller | `POST /api/workspaces` | Creates a workspace and automatically creates its Project, preserving the existing workspace response. |
11+
| Create another environment by forking | Existing workspace fork operation | Creates a child workspace in the source workspace's Project. |
12+
13+
Both POST endpoints are internal, session-authenticated APIs. `POST /api/projects` is not a public `/api/v2` endpoint and does not accept API-key principals. This foundation does not remove or deprecate existing workspace creation endpoints.
14+
15+
Do not call both creation endpoints for one onboarding flow: each creates a new workspace and a new Project. Neither endpoint attaches a workspace to an existing Project. A general Project environment-creation endpoint is follow-up work.
16+
17+
## Create a Project and its first environment
18+
19+
Use the shared client and contract for same-origin application calls:
20+
21+
```ts
22+
import { requestJson } from '@/lib/api/client/request'
23+
import { createProjectContract } from '@/lib/api/contracts/projects'
24+
25+
const result = await requestJson(createProjectContract, {
26+
body: {
27+
organizationId: selectedOrganizationId,
28+
name: 'Customer support',
29+
initialEnvironment: { name: 'Production' },
30+
},
31+
})
32+
```
33+
34+
All three inputs are required:
35+
36+
- `organizationId`: the intended organization's ID, or explicitly `null` for a personal Project. There is no fallback to the session's active organization. The caller must be eligible to create in the requested scope; an ineligible organization request is not silently converted to personal creation.
37+
- `name`: the Project name, trimmed and limited to 1–100 characters.
38+
- `initialEnvironment.name`: the first environment's name, also trimmed and limited to 1–100 characters. There is **no default environment name**; `Production` above is an example supplied by the caller.
39+
40+
For personal creation, use the same request with `organizationId: null`.
41+
42+
The HTTP 201 response contains both IDs and names:
43+
44+
```json
45+
{
46+
"project": { "id": "<project-id>", "name": "Customer support" },
47+
"initialEnvironment": { "id": "<workspace-id>", "name": "Production" }
48+
}
49+
```
50+
51+
`initialEnvironment.id` is the workspace ID for existing workspace routes and navigation.
52+
53+
The application operation creates the Project, workspace, Project membership, initial administrator permissions, and starter workflow in one database transaction. A failed transaction leaves none of these new records committed. This endpoint always includes the starter workflow; it has no `skipDefaultWorkflow` option.
54+
55+
Creation uses existing workspace eligibility, billing, and `workspace.create` permission-group rules. Choosing personal scope does not bypass applicable organization permission-group restrictions. This endpoint has no idempotency-key support: resubmitting after an uncertain network result can create another Project, so do not blindly retry.
56+
57+
## Existing workspace creation
58+
59+
Existing callers can continue to use `createWorkspaceContract` and `POST /api/workspaces` with their current body:
60+
61+
```json
62+
{
63+
"name": "Support workspace",
64+
"skipDefaultWorkflow": false
65+
}
66+
```
67+
68+
`skipDefaultWorkflow` remains optional and defaults to `false`. The route uses the session's active organization and existing workspace creation policy to resolve ownership and billing. It does not take the explicit Project scope or independent Project name used by `POST /api/projects`.
69+
70+
The workspace and its Project are still created atomically. The generated Project name is `Support workspace - Project`; long names are bounded to 100 characters while retaining the suffix. The response remains `{ "workspace": ... }` with HTTP 200, without a new Project response wrapper. Call `GET /api/projects/by-workspace/[workspaceId]` when an existing workspace caller needs its authorized Project details.
71+
72+
## Server implementation
73+
74+
The Project route calls `createProject` in `application/create-project.ts`. Existing workspace callers continue through their current creation paths. Both use the shared transaction primitive in `lib/workspaces/create.ts`; surface adapters must not independently commit Project and workspace creation.
75+
76+
Project descriptions and Project-scoped files are not part of this creation contract. Project-scoped files and a designated Project brief are follow-up work documented in the foundation plan.

‎docs/plans/project-entity-foundation.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ Every Project retains a required `ownerId`, including organization Projects. `or
270270

271271
The schema contains `project` (`id`, `name`, required `ownerId`, nullable `organizationId`, `archivedAt`, `createdAt`, `updatedAt`) and `project_workspace` (`projectId`, unique `workspaceId`, `createdAt`). There is no stored fork depth, position, or Project billing state.
272272

273+
For request/response examples and the distinction between explicit Project creation and existing workspace creation, see the [Project creation guide](../../apps/sim/lib/projects/README.md).
274+
273275
Implemented session routes:
274276

275277
- `POST /api/projects`: creates a named Project and its named first environment atomically, including admin permissions and a starter workflow. Requires explicit `organizationId` (or `null` for personal scope), `name`, and `initialEnvironment.name`; returns both IDs and names with HTTP 201. Uses existing workspace creation eligibility, billing and permission-group rules.

0 commit comments

Comments
 (0)