Swift On Server's

Published: (December 24, 2025 at 12:47 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Cover image for Swift On Server's

Vapor Drawing Backend – Project Overview

A collaborative note‑taking backend built with Vapor (Swift) that supports real‑time collaboration, authentication, and drawing‑strokes persistence.

Tech Stack

  • Framework: Vapor 4.115.0
  • Database: MongoDB with Fluent ORM
  • Authentication: JWT (JSON Web Tokens)
  • Real‑time: WebSockets
  • Language: Swift 6.0

Features Implemented

1. Authentication System

JWT‑based authentication with user registration and login functionality.

// User model with email and password
final class User: Model, Content, Authenticatable {
    static let schema = "users"

    @ID(key: .id)
    var id: UUID?

    @Field(key: "email")
    var email: String

    @Field(key: "password_hash")
    var passwordHash: String
}

Endpoints

  • POST /api/v1/auth/register – Register new user
  • POST /api/v1/auth/login – Login user
  • GET /api/v1/auth/me – Get current user (protected)

2. JWT Middleware

Custom middleware that verifies JWT tokens and protects routes.

struct AuthMiddleware: AsyncMiddleware {
    func respond(to request: Request, chainingTo next: any AsyncResponder) async throws -> Response {
        let payload: UserToken = try await request.jwt.verify(as: UserToken.self)

        guard let user = try await User.find(payload.userID, on: request.db) else {
            throw Abort(.unauthorized, reason: "User not found")
        }
        request.auth.login(user)

        return try await next.respond(to: request)
    }
}

3. MongoDB with Fluent ORM

Database configuration using FluentMongoDriver with automatic migrations.

// Configure MongoDB
try app.databases.use(
    .mongo(
        connectionString: Environment.get("MONGODB_URI") ?? "mongodb://localhost:27017"
    ),
    as: .mongo
)

// Run migrations
app.migrations.add(User.Migration())
app.migrations.add(NotesModel.Migration())

4. Notes Management

Full CRUD operations for notes with drawing‑stroke support.

final class NotesModel: Model, Content {
    @Field(key: "title")
    var title: String

    @Field(key: "strokes")
    var strokes: [DrawingStroke]

    @Parent(key: "user_id")
    var user: User
}

struct DrawingStroke: Codable {
    let points: [DrawingPoint]
    let color: DrawingColor
    let width: Double
    let timestamp: Date
}

Endpoints

  • POST /api/v1/notes – Create note
  • GET /api/v1/notes – Get all notes
  • GET /api/v1/notes/get/:id – Get single note
  • PUT /api/v1/notes/:id – Update note
  • DELETE /api/v1/notes/:id – Delete note

5. Real‑time WebSocket Collaboration

WebSocket manager for collaborative editing with note‑session management.

final class WebSocketManager {
    private var connections: [UUID: WebSocket] = [:]
    private var noteCollaborators: [UUID: Set] = [:]

    func joinNoteSession(noteID: UUID, userID: UUID)
    func leaveNoteSession(noteID: UUID, userID: UUID)
    func broadcastToNote(noteID: UUID, message: String, excludeUserID: UUID?)
}

WebSocket Features

  • Join/leave note sessions
  • Real‑time stroke updates
  • Broadcast to all collaborators (excluding sender)
  • Personal messaging

Endpoint: WS /api/v1/auth/handleInvite (protected)

6. Note Sharing

Share notes via JWT tokens with external users.

// Share token endpoint
GET /api/v1/notes/shared/:shareToken

// Verifies JWT token and returns note
let payload = try await req.jwt.verify(shareToken, as: ShareTokenPayload.self)

Project Structure

Sources/NoterPlayBackend/
├── Controllers/
│   ├── AuthenticationController.swift
│   ├── NotesController.swift
│   └── InviteController.swift
├── Middleware/
│   └── AuthMiddleware.swift
├── Models/
│   ├── User.swift
│   ├── NotesModel.swift
│   ├── UserToken.swift
│   ├── ShareTokenPayload.swift
│   └── InviteModel.swift
├── WSManager/
│   └── WebSocketManager.swift
├── configure.swift
└── routes.swift

Getting Started

# Install dependencies
swift package resolve

# Run the server
swift run

# With Docker
docker-compose up

Vapor Drawing Github

Built with ❤️ using Vapor and Swift.

Back to Blog

Related posts

Read more »

Swift #28: Foundation

markdown !David Goyeshttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fu...

Combine #13: Manejo de Recursos

share y multicast_: share La mayoría de los Publishers de Combine son struct que solo describen un pipeline, sin guardar un estado compartido. No se crea una i...