Initial implementation: multi-tenant Kanban board (Phase 1)
Complete Phase 1 foundation with working board, column, and card CRUD: - SvelteKit + TypeScript + Tailwind CSS v4 + adapter-node - Full Prisma schema with 18 tables (tenants, users, boards, columns, cards, etc.) - Multi-tenant architecture with hostname-based tenant resolution - Email/password auth with bcrypt + session cookies - Board/Column/Card API routes with full CRUD - Fractional indexing for drag-and-drop ordering - Board view with svelte-dnd-action for column and card drag-and-drop - Card modal with inline editing - Auth pages (login, register) - Board listing with create form - RLS policies SQL script for tenant isolation - Prisma RLS client extensions (forTenant/bypassRLS) - Permission helpers (canEditBoard, canManageMembers, etc.) - Socket.IO server setup (dev Vite plugin + production Express server) - Client-side socket store for real-time updates - Docker Compose (app + PostgreSQL 16) + multi-stage Dockerfile - Database seed script (default tenant + admin user) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import express from 'express';
|
||||
import { createServer } from 'http';
|
||||
import { Server } from 'socket.io';
|
||||
import { handler } from './build/handler.js';
|
||||
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: process.env.ORIGIN || 'http://localhost:3000',
|
||||
credentials: true
|
||||
}
|
||||
});
|
||||
|
||||
// Socket.IO auth + room management
|
||||
io.on('connection', (socket) => {
|
||||
console.log(`Socket connected: ${socket.id}`);
|
||||
|
||||
socket.on('join-board', (boardId) => {
|
||||
socket.join(`board:${boardId}`);
|
||||
socket.to(`board:${boardId}`).emit('user-joined', { socketId: socket.id });
|
||||
});
|
||||
|
||||
socket.on('leave-board', (boardId) => {
|
||||
socket.leave(`board:${boardId}`);
|
||||
socket.to(`board:${boardId}`).emit('user-left', { socketId: socket.id });
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(`Socket disconnected: ${socket.id}`);
|
||||
});
|
||||
});
|
||||
|
||||
// Store io globally so it can be accessed if needed
|
||||
globalThis.__socketIO = io;
|
||||
|
||||
// SvelteKit handler
|
||||
app.use(handler);
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Server running on http://${host}:${port}`);
|
||||
});
|
||||
Reference in New Issue
Block a user