mirror of
https://github.com/System-End/spaces.git
synced 2026-04-19 19:55:17 +00:00
readme
This commit is contained in:
parent
a515ed54ff
commit
c0333f3e74
4 changed files with 299 additions and 3 deletions
288
README.md
Normal file
288
README.md
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
# Spaces
|
||||
Spaces is a web app that allows access to visual studio code, kicad, and blender, inside of a web browser. It achieves this using container streaming. Spaces was developed by [Ivie Fonner](https://github.com/charmunks/) and [Hack Club](https://github.com/hackclub/)
|
||||
|
||||
## Setup:
|
||||
### Manual Setup:
|
||||
#### Prerequisites:
|
||||
Before installing, you must have docker set up and the daemon running. You must also have nodejs and npm installed.
|
||||
|
||||
#### Installation:
|
||||
```bash
|
||||
git clone https://github.com/hackclub/spaces-new.git
|
||||
|
||||
cp example.env .env # fill out the .env
|
||||
|
||||
npm install
|
||||
|
||||
npm run client-install
|
||||
|
||||
# run both client and server
|
||||
npm run dev
|
||||
|
||||
# run only backend
|
||||
npm run serve:server
|
||||
|
||||
# run only client
|
||||
npm run serve:client
|
||||
```
|
||||
|
||||
### Docker Setup:
|
||||
|
||||
#### Prerequisites:
|
||||
Before installing, you must have both docker and docker-compose set up and the daemon running.
|
||||
|
||||
### Installation:
|
||||
```bash
|
||||
git clone https://github.com/hackclub/spaces-new.git
|
||||
|
||||
cp example.env .env # make sure to set DOCKER=true
|
||||
|
||||
docker compose up --build
|
||||
# server is now live at localhost:2593
|
||||
```
|
||||
|
||||
### .env setup:
|
||||
|
||||
```bash
|
||||
# postgres database connection
|
||||
PG_CONNECTION_STRING=your-postgres-db-url
|
||||
# airtable credentials for email otps
|
||||
AIRTABLE_API_KEY=your-airtable-pat
|
||||
AIRTABLE_BASE_ID=your=airtable-baseid
|
||||
# port for backend server
|
||||
PORT=3000
|
||||
# set to true if using docker
|
||||
DOCKER=false
|
||||
```
|
||||
|
||||
## API Documentation:
|
||||
|
||||
By default the API will be accessible at `/api/v1`
|
||||
|
||||
### Authentication
|
||||
|
||||
All API endpoints that require authentication expect an `authorization` token in the request headers or body. This token is obtained during login/signup and must be included in subsequent requests.
|
||||
|
||||
### Users API (`/api/v1/users`)
|
||||
|
||||
#### Send Verification Code
|
||||
- **POST** `/api/v1/users/send`
|
||||
- **Description**: Send a verification code to the provided email address
|
||||
- **Body**:
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com"
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Verification code sent successfully",
|
||||
"data": {
|
||||
"email": "user@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Sign Up
|
||||
- **POST** `/api/v1/users/signup`
|
||||
- **Description**: Create a new user account with email verification
|
||||
- **Body**:
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"username": "myusername",
|
||||
"verificationCode": "123456"
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "User created successfully",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"email": "user@example.com",
|
||||
"username": "myusername",
|
||||
"authorization": "auth_token_here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Login
|
||||
- **POST** `/api/v1/users/login`
|
||||
- **Description**: Login with email and verification code
|
||||
- **Body**:
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"code": "123456"
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Login successful",
|
||||
"data": {
|
||||
"email": "user@example.com",
|
||||
"username": "myusername",
|
||||
"authorization": "new_auth_token_here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Sign Out
|
||||
- **POST** `/api/v1/users/signout`
|
||||
- **Description**: Sign out and invalidate the current authorization token
|
||||
- **Body**:
|
||||
```json
|
||||
{
|
||||
"authorization": "current_auth_token"
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Sign out successful",
|
||||
"data": {
|
||||
"email": "user@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Spaces API (`/api/v1/spaces`)
|
||||
|
||||
#### Create Container
|
||||
- **POST** `/api/v1/spaces/create`
|
||||
- **Description**: Create a new containerized workspace
|
||||
- **Headers**:
|
||||
- `authorization: your_auth_token`
|
||||
- **Body**:
|
||||
```json
|
||||
{
|
||||
"password": "container_password",
|
||||
"type": "code-server"
|
||||
}
|
||||
```
|
||||
- **Valid Types**: `code-server`, `blender`, `kicad`
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"message": "Container created successfully",
|
||||
"spaceId": 1,
|
||||
"containerId": "docker_container_id",
|
||||
"type": "code-server",
|
||||
"description": "VS Code Server",
|
||||
"image": "linuxserver/code-server",
|
||||
"port": 8080,
|
||||
"accessUrl": "http://localhost:8080"
|
||||
}
|
||||
```
|
||||
|
||||
#### Start Container
|
||||
- **POST** `/api/v1/spaces/start/:spaceId`
|
||||
- **Description**: Start an existing container
|
||||
- **Headers**:
|
||||
- `authorization: your_auth_token`
|
||||
- **Parameters**:
|
||||
- `spaceId`: The ID of the space to start
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"message": "Container started successfully",
|
||||
"spaceId": 1,
|
||||
"containerId": "docker_container_id"
|
||||
}
|
||||
```
|
||||
|
||||
#### Stop Container
|
||||
- **POST** `/api/v1/spaces/stop/:spaceId`
|
||||
- **Description**: Stop a running container
|
||||
- **Headers**:
|
||||
- `authorization: your_auth_token`
|
||||
- **Parameters**:
|
||||
- `spaceId`: The ID of the space to stop
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"message": "Container stopped successfully",
|
||||
"spaceId": 1,
|
||||
"containerId": "docker_container_id"
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Container Status
|
||||
- **GET** `/api/v1/spaces/status/:spaceId`
|
||||
- **Description**: Get the current status of a container
|
||||
- **Headers**:
|
||||
- `authorization: your_auth_token`
|
||||
- **Parameters**:
|
||||
- `spaceId`: The ID of the space to check
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"spaceId": 1,
|
||||
"containerId": "docker_container_id",
|
||||
"type": "code-server",
|
||||
"description": "VS Code Server",
|
||||
"accessUrl": "http://localhost:8080",
|
||||
"status": "running",
|
||||
"running": true,
|
||||
"startedAt": "2023-01-01T00:00:00.000Z",
|
||||
"finishedAt": "0001-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### List User Spaces
|
||||
- **GET** `/api/v1/spaces/list`
|
||||
- **Description**: Get all spaces owned by the authenticated user
|
||||
- **Headers**:
|
||||
- `authorization: your_auth_token`
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"message": "Spaces retrieved successfully",
|
||||
"spaces": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "code-server",
|
||||
"description": "VS Code Server",
|
||||
"image": "linuxserver/code-server",
|
||||
"port": 8080,
|
||||
"access_url": "http://localhost:8080",
|
||||
"created_at": "2023-01-01T00:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Container Types
|
||||
|
||||
| Type | Description | Image |
|
||||
|------|-------------|-------|
|
||||
| `code-server` | VS Code Server | `linuxserver/code-server` |
|
||||
| `blender` | Blender 3D | `linuxserver/blender` |
|
||||
| `kicad` | KiCad PCB Design | `linuxserver/kicad` |
|
||||
|
||||
### Error Responses
|
||||
|
||||
All endpoints return consistent error responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Error description",
|
||||
"error": "Detailed error (development only)"
|
||||
}
|
||||
```
|
||||
|
||||
Common HTTP status codes:
|
||||
- `400`: Bad Request (missing/invalid parameters)
|
||||
- `401`: Unauthorized (invalid/missing auth token)
|
||||
- `404`: Not Found (resource doesn't exist)
|
||||
- `409`: Conflict (duplicate email/username)
|
||||
- `500`: Internal Server Error
|
||||
|
||||
5
client/example.env
Normal file
5
client/example.env
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
PG_CONNECTION_STRING=your-postgres-db-url
|
||||
AIRTABLE_API_KEY=your-airtable-pat
|
||||
AIRTABLE_BASE_ID=your=airtable-baseid
|
||||
PORT=3000
|
||||
DOCKER=false
|
||||
|
|
@ -77,6 +77,10 @@ export const createContainer = async (password, type, authorization) => {
|
|||
})
|
||||
.returning(['id', 'container_id', 'type', 'description', 'image', 'port', 'access_url']);
|
||||
|
||||
if (process.env.DOCKER === 'true') {
|
||||
newSpace.access_url = `http://${process.env.SERVER_URL}/ports/${newSpace.port}`;
|
||||
}
|
||||
|
||||
return {
|
||||
message: "Container created successfully",
|
||||
spaceId: newSpace.id,
|
||||
|
|
|
|||
5
start.sh
5
start.sh
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Check if Docker is available (from host system)
|
||||
if docker info >/dev/null 2>&1; then
|
||||
echo "Docker is available from host system!"
|
||||
echo "Docker is available."
|
||||
else
|
||||
echo "Warning: Docker not available. Make sure Docker socket is mounted."
|
||||
echo "Warning: Docker not available. Make sure Docker is running."
|
||||
fi
|
||||
|
||||
# Start all services with supervisor
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue