Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
dd20337
changes to make the system better
christian-andersson Mar 21, 2025
1c66f36
add first iteration from claude-code
christian-andersson Mar 28, 2025
7ad67d4
fixes for authentication and registration
christian-andersson Mar 28, 2025
0fd5fff
fix registration and ping
christian-andersson Mar 28, 2025
7f79e14
loads of changes
christian-andersson Mar 29, 2025
dd96bdc
add profile page
christian-andersson Mar 29, 2025
1391015
some fixes
christian-andersson Mar 29, 2025
b184a0b
fix device pages
christian-andersson Mar 29, 2025
c1d4958
add playlist functionality
christian-andersson Mar 29, 2025
919c3f7
many updates
christian-andersson Mar 29, 2025
dc6b61b
change claim, settings, etc
christian-andersson Mar 31, 2025
4f3d9e8
more updates
christian-andersson Apr 12, 2025
4e02d89
Create CLAUDE.md
christian-andersson Apr 12, 2025
526022e
add private/public key handling for devices
christian-andersson Apr 12, 2025
7e401bd
add authentication endpoints.
christian-andersson Apr 12, 2025
d047a9c
add a lot of stuff, checks, etc
christian-andersson Apr 13, 2025
ba7d232
updates
christian-andersson Apr 13, 2025
d05fc96
changed by claude code
christian-andersson Apr 22, 2025
603b568
ADDED STUFF
christian-andersson May 12, 2025
ecd2556
refactor and consolidate migrations
christian-andersson May 15, 2025
f9af3ea
remove debug files
christian-andersson May 15, 2025
bb18c0a
Add XSS protection and tenant authorization middleware
christian-andersson Feb 19, 2026
764410a
Harden routes and controllers with security middleware
christian-andersson Feb 19, 2026
5037f0b
Update server and client dependencies
christian-andersson Feb 19, 2026
6fda2b2
Add security documentation and .env.example template
christian-andersson Feb 19, 2026
ad10684
Update and SHA-pin all GitHub Actions to latest versions
christian-andersson Feb 19, 2026
3063d98
Add .claude-memory-private and local settings to .gitignore
christian-andersson Feb 19, 2026
2dfaab5
Move documentation files to docs/ directory
christian-andersson Mar 13, 2026
6997df6
Migrate client from Create React App to Vite
christian-andersson Mar 13, 2026
0c70047
Add CSRF protection, CSP nonce injection, and harden server security
christian-andersson Mar 13, 2026
f0af339
Add csrfFetch wrapper and update client to use CSRF tokens
christian-andersson Mar 13, 2026
17c6ca9
Hash device API keys with SHA-256 instead of storing plaintext
christian-andersson Mar 13, 2026
58724ad
Harden auth controllers, routes, and services with input validation a…
christian-andersson Mar 13, 2026
a156c74
Add Jest testing infrastructure and security-focused tests
christian-andersson Mar 13, 2026
b59572e
Update server dependencies and add Jest, supertest, and express-rate-…
christian-andersson Mar 13, 2026
b915de7
Add .env files to .gitignore to prevent secret leaks
christian-andersson Mar 13, 2026
cc26cf2
Untrack server/.env to prevent committing secrets
christian-andersson Mar 13, 2026
4d6a2e4
Archive Node.js/Express server to server-node-archived/
christian-andersson Mar 13, 2026
dd61db7
Migrate server from Node.js/Express to Deno/Hono
christian-andersson Mar 13, 2026
5ee5ffe
Port test suite to Deno test runner (50 tests across 7 files)
christian-andersson Mar 13, 2026
213478c
Update Dockerfile, docs, and config for Deno server
christian-andersson Mar 13, 2026
42e4ff8
Remove old Node.js server files replaced by Deno migration
christian-andersson Mar 13, 2026
1600904
Add Vite build config for admin UI inside server directory
christian-andersson Mar 14, 2026
b434626
Move admin UI from client/ to server/admin/
christian-andersson Mar 14, 2026
12cde2d
Fix WebAuthn multi-origin, verification links, tenant auth, and UUIDv…
christian-andersson Mar 14, 2026
0988322
Update build, deploy, and docs for consolidated server/admin structure
christian-andersson Mar 14, 2026
5a205bd
Consolidate migrations into single initial schema and run at startup
christian-andersson Mar 14, 2026
e05e418
Rename playlist item url column to data and fix Zod null validation
christian-andersson Mar 14, 2026
5f56118
Fix device claiming, network insert null tenant, and add content endp…
christian-andersson Mar 14, 2026
b50c274
Add whole-day schedule option and remove dead PlaylistGroups page
christian-andersson Mar 14, 2026
63c9a17
Add CDP-based signage client with YouTube error recovery
christian-andersson Mar 14, 2026
110ec86
Add best-effort YouTube embeddability check via oEmbed API
christian-andersson Mar 14, 2026
d0fde80
Add image display settings (fit mode, background color)
christian-andersson Mar 14, 2026
2c55416
Add drag-to-reorder for playlist items
christian-andersson Mar 14, 2026
1595e30
Fix timestamp columns to use timestamptz to match Drizzle schema
christian-andersson Mar 14, 2026
bb5d256
Add QR code to status page for device identification
christian-andersson Mar 14, 2026
a8bc68b
Add common CSS and unify button styles across admin pages
christian-andersson Mar 14, 2026
686b479
Add playlist rename with edit button and modal
christian-andersson Mar 14, 2026
9e21bb4
Use common button styles for passkey edit/delete on Profile page
christian-andersson Mar 14, 2026
4ff0ec5
Add organization rename and delete with confirmation modal
christian-andersson Mar 14, 2026
1edf4f5
Replace user-facing 'tenant' with 'organization' in UI text
christian-andersson Mar 14, 2026
2d624b6
Fix empty user info in organization members list by flattening Drizzl…
christian-andersson Mar 14, 2026
88f96d1
Restyle role and status badges as subtle labels instead of button-lik…
christian-andersson Mar 14, 2026
e720b6d
Replace ownerId column with role-based ownership in tenant_members
christian-andersson Mar 15, 2026
a2f57eb
Add invite modal, role-based permission UI, and userRole field consis…
christian-andersson Mar 15, 2026
4a764db
Process pending invitations on signup and use Zod email validation co…
christian-andersson Mar 15, 2026
67de44b
Show clickable localhost URL on startup and disable build minification
christian-andersson Mar 15, 2026
1468eac
Defer user creation until passkey is verified
christian-andersson Mar 15, 2026
749ce25
Harden auth token reuse, verification link origin, and static file se…
christian-andersson Mar 15, 2026
a1d17f4
Run container as non-root and scope file read to /app/server
christian-andersson Mar 15, 2026
a37eb61
Use Deno for both build stages and run via deno task start
christian-andersson Mar 15, 2026
2562a81
Add Raspberry Pi provisioning tool for signage-client
christian-andersson Mar 15, 2026
e6c4145
Detect Pi model and adapt provisioning steps per hardware
christian-andersson Mar 15, 2026
b6e7743
Add cross-platform display detection and Windows support
christian-andersson Mar 15, 2026
1cffd92
Store device display info from heartbeat in database
christian-andersson Mar 15, 2026
c588d73
Replace single device campaignId with per-display campaign assignments
christian-andersson Mar 15, 2026
db5a32c
Defer email verification token deletion until registration completes
christian-andersson Mar 15, 2026
f13807a
Update signage-client for per-display content and fix stale device ID
christian-andersson Mar 15, 2026
9eddb71
Add per-item cookies and HTTP headers to playlist items
christian-andersson Mar 15, 2026
56dd7e8
Apply cookies and headers via CDP before each playlist item navigation
christian-andersson Mar 15, 2026
581975e
Add encrypted per-tenant secrets management
christian-andersson Mar 15, 2026
e0f0215
Add domain field to tenant secrets for URL-scoped enforcement
christian-andersson Mar 15, 2026
cb0aba6
Wire secrets into playlist item headers with domain enforcement
christian-andersson Mar 16, 2026
9b93180
Standardize action buttons across all admin pages
christian-andersson Mar 16, 2026
04a7bc3
Redesign Playlists page with sidebar layout and fix UI issues
christian-andersson Mar 16, 2026
4624cc0
Add test scripts to gitignore
christian-andersson Mar 16, 2026
e457890
Launch one Chrome per display with per-display campaign playback
christian-andersson Mar 16, 2026
4873e64
Use hardware IDs for stable display campaign assignments
christian-andersson Mar 16, 2026
220d7ae
Add clear all campaigns button and endpoint for device management
christian-andersson Mar 16, 2026
0bbb376
Remove archived Node.js server — fully replaced by Deno
christian-andersson Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

- name: Login to GHCR
uses: docker/login-action@v1
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{github.actor}}
password: ${{secrets.GITHUB_TOKEN}}

- name: build tag and push image
uses: docker/build-push-action@v2
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
platforms: linux/amd64
Expand Down
25 changes: 22 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
# build directory
# build output
build
dist

# Dependency directories
node_modules/


# ide directory
.idea
.idea
*.pem

# Environment files (contain secrets)
.env
server/.env

# Deno lock file
deno.lock

# Test scripts
test-*.sh

# Provisioning (SSH keys and saved config contain secrets)
provision_key
provision_key.pub
saved-config.json

.claude-memory-private
.claude/settings.local.json
75 changes: 75 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build and Run Commands
- Server: `cd server && deno task dev` (dev mode with watch), `deno task start` (production)
- Admin UI dev: `cd server && deno task dev:admin` (Vite dev server on port 3000)
- Admin UI build: `cd server && deno task build:admin` (outputs to server/dist/)
- Tests: `cd server && deno task test`
- Type check: `cd server && deno task check`
- Database:
- Migrations: `cd server && deno task db:migrate`, `deno task db:migrate:down`
- Migration files are in `server/migrations/` (uses node-pg-migrate)

## Server Stack
- **Runtime**: Deno
- **Framework**: Hono (Express-like API)
- **ORM**: Drizzle ORM with postgres.js driver
- **Validation**: Zod
- **Auth**: WebAuthn via @simplewebauthn/server
- **Session**: Custom PostgreSQL-backed session middleware
- **IDs**: UUIDv7 (time-ordered) for all database record IDs

## Admin UI Stack
- **Framework**: React 18 with TypeScript
- **Build**: Vite (deps in server/package.json)
- **Routing**: react-router-dom v6
- **Source**: `server/admin/` — built to `server/dist/`, served by the Deno server
- **Dev proxy**: Vite proxies /api to localhost:4000

## Project Structure
```
├── server/
│ ├── deno.json # Server config (Deno imports, tasks)
│ ├── package.json # Admin UI dependencies (React, Vite)
│ ├── vite.config.ts # Admin UI build config
│ ├── index.html # Vite entry point
│ ├── src/ # Hono API server
│ ├── admin/ # React admin UI source
│ ├── migrations/ # Database migrations
│ └── dist/ # Built admin UI output
└── shared/ # Shared TypeScript types
```

## Database Migrations
- Project uses node-pg-migrate for explicit, versioned migrations
- Migration files are in `server/migrations/` directory
- Each migration includes up (apply) and down (revert) functions

## Code Style Guidelines
- **Formatting**: 2-space indentation, single quotes, semicolons, trailing commas
- **Naming**: camelCase for variables/functions, PascalCase for classes/components
- **Imports**: 3rd-party first, project imports second, grouped by category; use `.ts` extensions for server code
- **Types**: Use TypeScript interfaces/types, explicit return types on functions
- **Error Handling**: try/catch blocks, error middleware (handleErrors wrapper), consistent response structure
- **Architecture**: Follow separation of concerns (controllers, services, repositories)
- **Components**: Use functional React components with hooks
- **State Management**: React hooks for local state

## Security Requirements
- All user input must be validated and sanitized both on the client side and server side
- Follow secure authentication practices with WebAuthn
- Implement proper authorization checks for API endpoints
- Never log sensitive information (credentials, tokens, PII)
- Use parameterized queries to prevent SQL injection
- Apply multi-tenant data isolation throughout the application
- **Session Security**: Use cryptographically secure session secrets (minimum 32 characters)
- Generate with: `deno eval "const a=new Uint8Array(32);crypto.getRandomValues(a);console.log(Array.from(a,b=>b.toString(16).padStart(2,'0')).join(''))"`
- Never use default/example secrets in production
- **XSS Protection**: Comprehensive Cross-Site Scripting prevention implemented
- Automatic input sanitization and output encoding
- Content Security Policy (CSP) headers with per-request nonces
- **Tenant Authorization**: Comprehensive multi-tenant authorization system
- Role-based access control (Owner/Admin/Member roles)
- Cached membership validation for performance (5-min TTL)
68 changes: 35 additions & 33 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
# ---- Base Node ----
FROM node:lts AS base
WORKDIR /usr/src/app

# ---- client ----
FROM base AS clientbuild
WORKDIR /usr/src/app
COPY client/ ./client
COPY shared/ ./shared

WORKDIR /usr/src/app/client
RUN ls -lrt
RUN npm ci
RUN npm run build

# ---- server ----
FROM base AS serverbuild
WORKDIR /usr/src/app
COPY server/ ./server
COPY shared/ ./shared

WORKDIR /usr/src/app/server
RUN ls -lrt
RUN npm ci
RUN npm run build

# ---- Release ----
FROM base AS release
# ---- Admin UI Build ----
FROM denoland/deno:2 AS adminbuild
WORKDIR /app

# Install npm dependencies
COPY server/package.json server/package-lock.json* ./
COPY server/.npmrc server/deno.json ./
RUN deno run -A npm:npm ci

# Build admin UI (matches deno task build:admin)
COPY server/admin/ ./admin/
COPY server/public/ ./public/
COPY server/index.html server/vite.config.ts server/tsconfig.json ./
RUN deno task build:admin

# ---- Server ----
FROM denoland/deno:2 AS release
LABEL org.opencontainers.image.source="https://github.com/Tripletex/SimpleDigitalSignageServer"
COPY --from=clientbuild /usr/src/app/client/build ./client/
COPY --from=serverbuild /usr/src/app/server/ ./server
ENV CLIENT_PATH=../../../../client/
WORKDIR /usr/src/app/server
WORKDIR /app/server

# Copy server source and config
COPY server/deno.json server/.npmrc ./
COPY server/src/ ./src/
COPY server/migrations/ ./migrations/

# Cache dependencies
RUN deno cache src/main.ts

# Copy built admin UI
COPY --from=adminbuild /app/dist ./dist/

# Run as non-root user (deno user is provided by the base image)
USER deno

EXPOSE 4000
CMD [ "node", "build/server/src/server.js" ]

CMD ["deno", "task", "start"]
89 changes: 88 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,89 @@
# SimpleDigitalSignageServer
This is the very beginning of the Simple digital Signage Server project, this is the very initial setup, more will come in the future,

A Digital Signage Server for managing devices, playlists, and multi-tenant organizations. Includes an admin UI for management and serves a signage client on Raspberry Pi devices.

## Tech Stack

- **Runtime**: [Deno](https://deno.land/)
- **Server**: Hono + Drizzle ORM (PostgreSQL)
- **Admin UI**: React 18 + Vite + TypeScript
- **Auth**: WebAuthn (passkeys)
- **Validation**: Zod

## Development Setup

### Prerequisites

- [Deno](https://deno.land/) (latest)
- Docker and Docker Compose (for PostgreSQL)
- Node.js (for admin UI dependencies / Vite)

### Quick Start

```bash
# Start PostgreSQL
docker-compose up -d

# Install admin UI dependencies
cd server && npm install

# Copy and configure environment
cp .env.example .env
# Edit .env with your settings

# Run database migrations
deno task db:migrate

# Start the server (port 4000)
deno task dev

# In another terminal, start the admin UI dev server (port 3000)
deno task dev:admin
```

### Available Tasks (run from `server/`)

```bash
deno task dev # Start server with auto-reload
deno task dev:admin # Start Vite dev server for admin UI
deno task start # Start server (production)
deno task build:admin # Build admin UI for production
deno task test # Run all tests
deno task check # Type-check server code
deno task db:migrate # Run database migrations
deno task db:migrate:down # Revert last migration
```

### Environment Variables

Copy `server/.env.example` to `server/.env` and configure:
- `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` — PostgreSQL connection
- `SESSION_SECRET` — Cryptographically secure session secret (min 32 chars)
- `RP_ID`, `ORIGIN` — WebAuthn relying party config

### Project Structure

```
├── server/
│ ├── deno.json # Server config (Deno imports, tasks)
│ ├── package.json # Admin UI dependencies (React, Vite)
│ ├── vite.config.ts # Admin UI build config
│ ├── index.html # Vite entry point
│ ├── src/ # Hono API server
│ ├── admin/ # React admin UI source
│ ├── migrations/ # Database migrations (node-pg-migrate)
│ └── dist/ # Built admin UI output
├── shared/ # Shared TypeScript types
└── docker-compose.yml # PostgreSQL dev setup
```

## API Endpoints

- `POST /api/device/register` - Register a new device
- `GET /api/device/list` - List all registered devices
- `GET /api/device/:id` - Get a specific device by ID

## Source Code

This project is open source and available on GitHub:
[SimpleDigitalSignageServer](https://github.com/Tripletex/SimpleDigitalSignageServer)
23 changes: 0 additions & 23 deletions client/.gitignore

This file was deleted.

46 changes: 0 additions & 46 deletions client/README.md

This file was deleted.

Loading
Loading