Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/node-lint-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22, 23]
node-version: [23, 24, 25]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22, 23]
node-version: [23, 24, 25]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -57,7 +57,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22, 23]
node-version: [23, 24, 25]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -83,7 +83,7 @@ jobs:
needs: build
strategy:
matrix:
node-version: [22, 23]
node-version: [23, 24, 25]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/node-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: 22
node-version: 25
cache: npm

- name: Install dependencies
Expand Down
32 changes: 30 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
.PHONY: install dev build lint seed import test clean clean-db clean-all clean-deps docker-build docker-run docker-stop docker-logs docker-clean docker-shell docker-db-backup docker-db-restore compose-up compose-down compose-logs compose-restart compose-clean help
.PHONY: install dev dev-https dev-insecure build lint seed import test clean clean-db clean-all clean-deps docker-build docker-run docker-run-insecure docker-stop docker-logs docker-clean docker-shell docker-db-backup docker-db-restore compose-up compose-up-insecure compose-down compose-logs compose-restart compose-clean help

help:
@echo "Development Commands"
@echo "===================="
@echo "make install - Install npm dependencies"
@echo "make dev - Start development server"
@echo "make dev - Start development server (HTTP)"
@echo "make dev-https - Start dev server with auto HTTPS (self-signed cert via Next.js)"
@echo "make dev-insecure - Start dev server with TLS verification disabled (INSECURE_TLS=1)"
@echo "make build - Full production build (seed + import + build)"
@echo "make lint - Run ESLint"
@echo "make seed - Create/reset database tables"
Expand All @@ -22,6 +24,7 @@ help:
@echo "===================="
@echo "make docker-build - Build Docker image"
@echo "make docker-run - Run container (Docker CLI)"
@echo "make docker-run-insecure - Run container with TLS verification disabled (INSECURE_TLS=1)"
@echo "make docker-stop - Stop container"
@echo "make docker-logs - View container logs"
@echo "make docker-clean - Remove container and image"
Expand All @@ -32,6 +35,7 @@ help:
@echo "Docker Compose Commands"
@echo "======================"
@echo "make compose-up - Start services with Docker Compose"
@echo "make compose-up-insecure - Start services with TLS verification disabled (INSECURE_TLS=1)"
@echo "make compose-down - Stop services"
@echo "make compose-logs - View Docker Compose logs"
@echo "make compose-restart - Restart services"
Expand All @@ -44,6 +48,12 @@ install:
dev:
npm run dev

dev-https:
npm run dev:https

dev-insecure:
INSECURE_TLS=1 npm run dev

build:
mkdir -p data
npm run db:seed
Expand Down Expand Up @@ -110,12 +120,25 @@ docker-run: docker-build
@echo "Running container..."
docker run -d \
-p 3000:3000 \
-e SESSION_SECRET=supersecretkeysupersecretkey3232 \
-v learning-platform-data:/app/data \
--name learning-platform \
--restart unless-stopped \
learning-platform:latest
@echo "Container started: http://localhost:3000"

docker-run-insecure: docker-build
@echo "Running container with TLS verification disabled..."
docker run -d \
-p 3000:3000 \
-e SESSION_SECRET=supersecretkeysupersecretkey3232 \
-e INSECURE_TLS=1 \
-v learning-platform-data:/app/data \
--name learning-platform \
--restart unless-stopped \
learning-platform:latest
@echo "Container started (insecure TLS): http://localhost:3000"

docker-stop:
@echo "Stopping container..."
docker stop learning-platform || true
Expand Down Expand Up @@ -157,6 +180,11 @@ compose-up:
docker-compose up -d
@echo "Services started: http://localhost:3000"

compose-up-insecure:
@echo "Starting services with TLS verification disabled..."
INSECURE_TLS=1 docker-compose up -d
@echo "Services started (insecure TLS): http://localhost:3000"

compose-down:
@echo "Stopping services..."
docker-compose down
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ services:
NODE_ENV: production
PORT: ${PORT:-3000}
HOST: ${HOST:-0.0.0.0}
INSECURE_TLS: ${INSECURE_TLS:-0}
volumes:
# Persist SQLite database
- learning-platform-data:/app/data
Expand Down
13 changes: 13 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const nextConfig = require("eslint-config-next/core-web-vitals");

module.exports = [
...nextConfig,
{
files: ["**/*.ts", "**/*.tsx"],
rules: {
"@typescript-eslint/no-explicit-any": "warn",
// Disabled: intentional Next.js SSR-safe pattern (localStorage access in mount effects)
"react-hooks/set-state-in-effect": "off",
},
},
];
34 changes: 34 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,46 @@

const pkg = JSON.parse(readFileSync("./package.json", "utf-8"));

// Allow disabling TLS certificate verification for environments with
// self-signed certs or corporate proxies (set INSECURE_TLS=1).
// Works in both development and production containers (e.g. docker-run-insecure).
if (process.env.INSECURE_TLS === "1") {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
console.warn(
`WARNING: TLS certificate verification is disabled (INSECURE_TLS=1) — NODE_ENV=${process.env.NODE_ENV}`
);
}

const isDev = process.env.NODE_ENV !== "production";
const isInsecure = process.env.INSECURE_TLS === "1";

const nextConfig: NextConfig = {
serverExternalPackages: ["better-sqlite3"],
output: "standalone",
env: {
NEXT_PUBLIC_APP_VERSION: pkg.version,
},
// Apply permissive headers in development OR when INSECURE_TLS=1 is set
// (e.g. docker-run-insecure). Prevents the browser from caching HSTS for
// localhost and unblocks Next.js inline bootstrap scripts over plain HTTP.
async headers() {
if (!isDev && !isInsecure) return [];
return [
{
source: "/(.*)",
headers: [
// Expire HSTS immediately so the browser stops upgrading HTTP→HTTPS.
{ key: "Strict-Transport-Security", value: "max-age=0" },
// Allow unsafe-inline so Next.js inline scripts are not blocked.
{
key: "Content-Security-Policy",
value:
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' ws: wss:;",
},
],
},
];
},
};

export default nextConfig;
Loading
Loading