A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add Docker deployment configuration

- Create multi-stage Dockerfile for backend (alpine, <50MB)
- Create Dockerfile for frontend with nginx
- Add nginx configuration with gzip, caching, and security headers
- Create docker-compose.yml with health checks and volumes
- Add Makefile with common commands (build, up, down, logs, etc.)
- Add .dockerignore files for both services
- Configure environment variables in docker-compose
- Add health check endpoints for monitoring

+321
+73
Makefile
··· 1 + .PHONY: help build up down logs clean dev-backend dev-frontend test 2 + 3 + help: ## Show this help message 4 + @echo 'Usage: make [target]' 5 + @echo '' 6 + @echo 'Available targets:' 7 + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST) 8 + 9 + build: ## Build Docker images 10 + docker-compose build 11 + 12 + up: ## Start all services 13 + docker-compose up -d 14 + @echo "" 15 + @echo "✓ MarkEdit is running!" 16 + @echo " Frontend: http://localhost:4321" 17 + @echo " Backend: http://localhost:8080" 18 + @echo "" 19 + @echo "To view logs: make logs" 20 + 21 + down: ## Stop all services 22 + docker-compose down 23 + 24 + logs: ## View logs from all services 25 + docker-compose logs -f 26 + 27 + logs-backend: ## View backend logs 28 + docker-compose logs -f backend 29 + 30 + logs-frontend: ## View frontend logs 31 + docker-compose logs -f frontend 32 + 33 + restart: ## Restart all services 34 + docker-compose restart 35 + 36 + clean: ## Remove containers, volumes, and images 37 + docker-compose down -v 38 + docker-compose rm -f 39 + @echo "Cleaned up containers and volumes" 40 + 41 + dev-backend: ## Run backend in development mode 42 + cd backend && go run cmd/server/main.go 43 + 44 + dev-frontend: ## Run frontend in development mode 45 + cd frontend && bun run dev 46 + 47 + install-backend: ## Install backend dependencies 48 + cd backend && go mod download 49 + 50 + install-frontend: ## Install frontend dependencies 51 + cd frontend && bun install 52 + 53 + test-backend: ## Run backend tests 54 + cd backend && go test ./... 55 + 56 + setup: ## Initial setup (copy .env.example to .env) 57 + @if [ ! -f .env ]; then \ 58 + cp .env.example .env; \ 59 + echo "✓ Created .env file from .env.example"; \ 60 + echo "⚠ Please edit .env and add your GitHub OAuth credentials"; \ 61 + else \ 62 + echo "⚠ .env file already exists"; \ 63 + fi 64 + 65 + db-migrate: ## Run database migrations 66 + cd backend && go run cmd/server/main.go migrate 67 + 68 + health: ## Check health of all services 69 + @echo "Checking backend health..." 70 + @curl -s http://localhost:8080/api/health | jq . || echo "Backend not responding" 71 + @echo "" 72 + @echo "Checking frontend health..." 73 + @curl -s http://localhost:4321/health || echo "Frontend not responding"
+31
backend/.dockerignore
··· 1 + # Development files 2 + .env 3 + .env.* 4 + *.log 5 + 6 + # Git 7 + .git 8 + .gitignore 9 + 10 + # IDE 11 + .vscode 12 + .idea 13 + *.swp 14 + *.swo 15 + 16 + # Data directories 17 + data/ 18 + *.db 19 + *.db-shm 20 + *.db-wal 21 + 22 + # Test files 23 + *_test.go 24 + testdata/ 25 + 26 + # Documentation 27 + *.md 28 + !README.md 29 + 30 + # CI/CD 31 + .github/
+48
backend/Dockerfile
··· 1 + # Build stage 2 + FROM golang:1.24-alpine AS builder 3 + 4 + # Install build dependencies 5 + RUN apk add --no-cache git gcc musl-dev 6 + 7 + WORKDIR /build 8 + 9 + # Copy go mod files 10 + COPY go.mod go.sum ./ 11 + RUN go mod download 12 + 13 + # Copy source code 14 + COPY . . 15 + 16 + # Build the binary 17 + RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags="-s -w" -o markedit ./cmd/server 18 + 19 + # Runtime stage 20 + FROM alpine:latest 21 + 22 + # Install ca-certificates for HTTPS and git for git operations 23 + RUN apk --no-cache add ca-certificates git 24 + 25 + WORKDIR /app 26 + 27 + # Copy binary from builder 28 + COPY --from=builder /build/markedit . 29 + 30 + # Copy migrations 31 + COPY --from=builder /build/internal/database/migrations ./internal/database/migrations 32 + 33 + # Create data directories 34 + RUN mkdir -p /app/data/repos 35 + 36 + # Expose port 37 + EXPOSE 8080 38 + 39 + # Run as non-root user 40 + RUN adduser -D -u 1000 markedit 41 + RUN chown -R markedit:markedit /app 42 + USER markedit 43 + 44 + # Health check 45 + HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 46 + CMD wget --no-verbose --tries=1 --spider http://localhost:8080/api/health || exit 1 47 + 48 + CMD ["./markedit"]
+68
docker-compose.yml
··· 1 + version: '3.8' 2 + 3 + services: 4 + backend: 5 + build: 6 + context: ./backend 7 + dockerfile: Dockerfile 8 + container_name: markedit-backend 9 + ports: 10 + - "8080:8080" 11 + environment: 12 + # Server 13 + - PORT=8080 14 + - FRONTEND_URL=http://localhost:4321 15 + - ALLOWED_ORIGINS=http://localhost:4321,http://localhost 16 + 17 + # GitHub OAuth (set these in .env file) 18 + - GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID} 19 + - GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET} 20 + - GITHUB_REDIRECT_URL=http://localhost:8080/api/auth/github/callback 21 + 22 + # Session 23 + - SESSION_SECRET=${SESSION_SECRET:-change-me-in-production} 24 + - SESSION_SECURE=false 25 + - SESSION_MAX_AGE=86400 26 + 27 + # Database 28 + - DATABASE_PATH=/app/data/markedit.db 29 + 30 + # Git 31 + - GIT_CACHE_DIR=/app/data/repos 32 + - GIT_AUTHOR_NAME=MarkEdit 33 + - GIT_AUTHOR_EMAIL=markedit@users.noreply.github.com 34 + 35 + # Logging 36 + - LOG_LEVEL=info 37 + volumes: 38 + - markedit-data:/app/data 39 + restart: unless-stopped 40 + healthcheck: 41 + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/api/health"] 42 + interval: 30s 43 + timeout: 3s 44 + retries: 3 45 + start_period: 5s 46 + 47 + frontend: 48 + build: 49 + context: ./frontend 50 + dockerfile: Dockerfile 51 + container_name: markedit-frontend 52 + ports: 53 + - "4321:80" 54 + environment: 55 + - PUBLIC_API_URL=http://localhost:8080 56 + depends_on: 57 + - backend 58 + restart: unless-stopped 59 + healthcheck: 60 + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"] 61 + interval: 30s 62 + timeout: 3s 63 + retries: 3 64 + start_period: 5s 65 + 66 + volumes: 67 + markedit-data: 68 + driver: local
+34
frontend/.dockerignore
··· 1 + # Dependencies 2 + node_modules/ 3 + 4 + # Development files 5 + .env 6 + .env.* 7 + *.log 8 + 9 + # Git 10 + .git 11 + .gitignore 12 + 13 + # IDE 14 + .vscode 15 + .idea 16 + *.swp 17 + *.swo 18 + 19 + # Build output (will be created during build) 20 + dist/ 21 + .astro/ 22 + 23 + # Test files 24 + **/*.test.ts 25 + **/*.test.tsx 26 + **/*.spec.ts 27 + **/*.spec.tsx 28 + 29 + # Documentation 30 + *.md 31 + !README.md 32 + 33 + # CI/CD 34 + .github/
+32
frontend/Dockerfile
··· 1 + # Build stage 2 + FROM oven/bun:1 AS builder 3 + 4 + WORKDIR /build 5 + 6 + # Copy package files 7 + COPY package.json bun.lock ./ 8 + RUN bun install --frozen-lockfile 9 + 10 + # Copy source code 11 + COPY . . 12 + 13 + # Build the application 14 + RUN bun run build 15 + 16 + # Runtime stage - serve with nginx 17 + FROM nginx:alpine 18 + 19 + # Copy built files 20 + COPY --from=builder /build/dist /usr/share/nginx/html 21 + 22 + # Copy nginx configuration 23 + COPY nginx.conf /etc/nginx/conf.d/default.conf 24 + 25 + # Expose port 26 + EXPOSE 80 27 + 28 + # Health check 29 + HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 30 + CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1 31 + 32 + CMD ["nginx", "-g", "daemon off;"]
+35
frontend/nginx.conf
··· 1 + server { 2 + listen 80; 3 + server_name localhost; 4 + root /usr/share/nginx/html; 5 + index index.html; 6 + 7 + # Gzip compression 8 + gzip on; 9 + gzip_vary on; 10 + gzip_min_length 1024; 11 + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; 12 + 13 + # Security headers 14 + add_header X-Frame-Options "SAMEORIGIN" always; 15 + add_header X-Content-Type-Options "nosniff" always; 16 + add_header X-XSS-Protection "1; mode=block" always; 17 + 18 + # Cache static assets 19 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { 20 + expires 1y; 21 + add_header Cache-Control "public, immutable"; 22 + } 23 + 24 + # Handle client-side routing 25 + location / { 26 + try_files $uri $uri/ /index.html; 27 + } 28 + 29 + # Health check endpoint 30 + location /health { 31 + access_log off; 32 + return 200 "healthy\n"; 33 + add_header Content-Type text/plain; 34 + } 35 + }