newOS for Developers

Back to Workflows Hub

Image Upload

intermediate

Complete S3 presigned URL flow for uploading images and files.

Endpoints

POST /postCreate post placeholder
POST /post/uploadGet presigned S3 URL
PUT /mood/attach/postAttach post to mood

Upload State Machine

type PostUploadState = {
  status: "preparing" | "created" | "attached" | "upload-requested" | "uploaded";
  blob: Blob;              // Original file blob
  filename: string;        // Original filename
  thumb: string;           // Base64 thumbnail for preview
  foldersToAttach: { id: string }[];  // Target moods
};

Implementation

import { createPostMultiple, execProgressiveHandler } from "newgraph-signals";

// Upload files to a mood
await execProgressiveHandler(createPostMultiple, {
  files: [file1, file2],           // File objects from input
  foldersToAttach: ["mood-id"],    // Target mood IDs
  content: "Optional description", // Text content
  contentMode: "last"              // Where to add content: "first" | "last" | "each"
});

// The upload queue signal tracks progress
import { uploadQueueSignal } from "newgraph-signals";

// Watch for completion
effect(() => {
  const queue = uploadQueueSignal.value;
  if (queue.length === 0) {
    console.log("All uploads complete!");
  }
});

Upload Flow

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ initializePost  │     │ createPostOn    │     │ updateAndAttach │
│ Upload()        │ ──▶ │ Server()        │ ──▶ │ ()              │
│ status:         │     │ POST /post      │     │ PUT /mood/      │
│ "preparing"     │     │ status:"created"│     │ attach/post     │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
                                                         │
┌─────────────────┐     ┌─────────────────┐     ┌────────▼────────┐
│  uploadFile()   │ ──▶ │  PUT to S3      │ ──▶ │  POST /post/    │
│  status:        │     │  presigned URL  │     │  upload         │
│  "uploaded"     │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘

Stage Functions

StageFunctionAPI Call
preparinginitializePostUpload()Local cache only
createdcreatePostOnServer()POST /post
attachedupdateAndAttach()PUT /mood/attach/post
uploadeduploadFile()POST /post/upload + PUT S3

Edge Cases

Content type required — File must have a valid MIME type
Presigned URL expiry — S3 URLs expire after 5 minutes
Retry logic — Failed stages are automatically retried
Text-only posts — Can skip file upload if contentType is text/plain