init
This commit is contained in:
parent
819f52241c
commit
bcea6da633
|
@ -0,0 +1,145 @@
|
|||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# Virtual environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Node.js
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
build/
|
||||
.vite/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids/
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Coverage
|
||||
.coverage
|
||||
.nyc_output
|
||||
coverage/
|
||||
|
||||
# Dependency directories
|
||||
jspm_packages/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Storybook build outputs
|
||||
.out
|
||||
.storybook-out
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Docker
|
||||
.dockerignore
|
||||
|
||||
# Production
|
||||
.env.production
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
|
@ -0,0 +1,11 @@
|
|||
# FastAPI Configuration
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
DEBUG=false
|
||||
|
||||
# CORS Settings
|
||||
CORS_ORIGINS=https://slow-reader.velouria.dev
|
||||
|
||||
# Application Settings
|
||||
APP_NAME=Slow Reader API
|
||||
VERSION=1.0.0
|
|
@ -0,0 +1,30 @@
|
|||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
g++ \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy project files
|
||||
COPY pyproject.toml ./
|
||||
COPY backend/ ./backend/
|
||||
|
||||
# Install uv
|
||||
RUN pip install uv
|
||||
|
||||
# Install dependencies
|
||||
RUN uv pip install --system -r pyproject.toml
|
||||
|
||||
# Download NLTK data
|
||||
RUN python -c "import nltk; nltk.download('punkt'); nltk.download('punkt_tab')"
|
||||
|
||||
# Create non-root user
|
||||
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@ -0,0 +1,48 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: backend/Dockerfile
|
||||
restart: always
|
||||
networks:
|
||||
- default
|
||||
- traefik_network
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.slow-reader-api.rule=Host(`slow-reader.velouria.dev`) && (PathPrefix(`/api/`) || PathPrefix(`/ws/`))"
|
||||
- "traefik.http.routers.slow-reader-api.entrypoints=websecure"
|
||||
- "traefik.http.routers.slow-reader-api.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.slow-reader-api.loadbalancer.server.port=8000"
|
||||
- "traefik.docker.network=traefik_network"
|
||||
- "homepage.group=Tools"
|
||||
- "homepage.name=Slow Reader API"
|
||||
- "homepage.description=Reading Focus API"
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
restart: always
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- default
|
||||
- traefik_network
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.slow-reader.rule=Host(`slow-reader.velouria.dev`)"
|
||||
- "traefik.http.routers.slow-reader.entrypoints=websecure"
|
||||
- "traefik.http.routers.slow-reader.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.slow-reader.loadbalancer.server.port=80"
|
||||
- "traefik.docker.network=traefik_network"
|
||||
- "homepage.group=Tools"
|
||||
- "homepage.name=Slow Reader"
|
||||
- "homepage.description=Focused Reading Experience"
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: slow-reader_default
|
||||
traefik_network:
|
||||
external: true
|
|
@ -0,0 +1,41 @@
|
|||
# Build stage
|
||||
FROM node:18-alpine as build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy built assets from build stage
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
|
||||
# Copy nginx configuration
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 -S appuser && \
|
||||
adduser -S appuser -u 1001 -G appuser && \
|
||||
chown -R appuser:appuser /usr/share/nginx/html && \
|
||||
chown -R appuser:appuser /var/cache/nginx && \
|
||||
chown -R appuser:appuser /var/log/nginx && \
|
||||
chown -R appuser:appuser /etc/nginx/conf.d && \
|
||||
touch /var/run/nginx.pid && \
|
||||
chown -R appuser:appuser /var/run/nginx.pid
|
||||
|
||||
USER appuser
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
|
@ -0,0 +1,37 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Enable gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline' 'unsafe-eval'" always;
|
||||
|
||||
# Handle client-side routing
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Cache HTML with shorter expiry
|
||||
location ~* \.html$ {
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
}
|
|
@ -299,7 +299,11 @@ That's what Slow Reader is about. Just you and the text, moving at a pace that l
|
|||
},
|
||||
|
||||
connectWebSocket() {
|
||||
const wsUrl = `ws://localhost:8000/ws/reading-session`
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
const host = window.location.host
|
||||
const wsUrl = import.meta.env.DEV
|
||||
? `ws://localhost:8000/ws/reading-session`
|
||||
: `${protocol}//${host}/ws/reading-session`
|
||||
this.websocket = new WebSocket(wsUrl)
|
||||
|
||||
this.websocket.onopen = () => {
|
||||
|
@ -556,7 +560,8 @@ That's what Slow Reader is about. Just you and the text, moving at a pace that l
|
|||
this.extractedArticle = null
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/extract-article', {
|
||||
const apiBase = import.meta.env.DEV ? '/api' : '/api'
|
||||
const response = await fetch(`${apiBase}/extract-article`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
@ -633,7 +638,8 @@ That's what Slow Reader is about. Just you and the text, moving at a pace that l
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/analyze-text', {
|
||||
const apiBase = import.meta.env.DEV ? '/api' : '/api'
|
||||
const response = await fetch(`${apiBase}/analyze-text`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
|
|
@ -17,6 +17,19 @@ export default defineConfig({
|
|||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
assetsDir: 'assets',
|
||||
sourcemap: false,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
vendor: ['vue'],
|
||||
pdfjs: ['pdfjs-dist']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['pdfjs-dist']
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue