DEV Community

Cover image for Swift On Server's
Amritesh Kumar
Amritesh Kumar Subscriber

Posted on

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
}
Enter fullscreen mode Exit fullscreen mode

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 authentication 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)
    }
}
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

4. Notes Management

Full CRUD operations for notes with drawing strokes 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
}
Enter fullscreen mode Exit fullscreen mode

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 real-time collaborative editing with note session management.

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

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

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Getting Started

# Install dependencies
swift package resolve

# Run the server
swift run

# With Docker
docker-compose up
Enter fullscreen mode Exit fullscreen mode

Vapor Drawing Github

A lot to more to Fix it Up exploring just a small prototype.

Built with ❤️ using Vapor and Swift

Top comments (0)