From ca93235cde3ae8f4bf00f2fcd7c5abe3ce8bf07a Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sat, 17 Jan 2026 18:38:03 +0000 Subject: [PATCH] Generated by Spark: I can auto default to flask backend with docker environment variable. If its not set used IndexedDB. --- .dockerignore | 16 ++ .env.example | 4 + BACKEND-CONFIG.md | 260 +++++++++++++++++++++++++++ Dockerfile | 25 +++ IMPLEMENTATION.md | 202 +++++++++++++++++++++ QUICKSTART.md | 267 ++++++++++++++++++++++++++++ README-APP.md | 71 +++++++- README.md | 102 +++++++++-- backend/README.md | 26 +++ docker-compose.README.md | 71 ++++++++ docker-compose.backend-only.yml | 15 ++ docker-compose.yml | 13 ++ nginx.conf | 19 ++ src/App.tsx | 8 + src/components/BackendIndicator.tsx | 53 ++++++ src/lib/db.ts | 8 +- src/lib/storage.ts | 28 ++- src/pages/SettingsPage.tsx | 87 ++++++++- src/vite-end.d.ts | 10 +- 19 files changed, 1253 insertions(+), 32 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 BACKEND-CONFIG.md create mode 100644 Dockerfile create mode 100644 IMPLEMENTATION.md create mode 100644 QUICKSTART.md create mode 100644 docker-compose.README.md create mode 100644 docker-compose.backend-only.yml create mode 100644 nginx.conf create mode 100644 src/components/BackendIndicator.tsx diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cbcf025 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +node_modules +dist +.git +.github +.env +.env.local +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.DS_Store +.vscode +.idea +backend +data +pids diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..aaa0e48 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Flask Backend Configuration (Optional) +# If set, the app will automatically use Flask backend instead of IndexedDB +# Example: VITE_FLASK_BACKEND_URL=http://localhost:5000 +VITE_FLASK_BACKEND_URL= diff --git a/BACKEND-CONFIG.md b/BACKEND-CONFIG.md new file mode 100644 index 0000000..63d8edf --- /dev/null +++ b/BACKEND-CONFIG.md @@ -0,0 +1,260 @@ +# Backend Configuration Guide + +This guide explains how to configure CodeSnippet to use different storage backends. + +## Storage Options + +CodeSnippet supports two storage backends: + +### 1. IndexedDB (Default) +- **Local browser storage** using SQLite compiled to WebAssembly +- No server required +- Data persists only on the current device/browser +- Best for personal use or offline scenarios + +### 2. Flask Backend +- **Remote server storage** with a Flask REST API +- Requires running a Flask backend server +- Data accessible from any device +- Best for team use or multi-device access + +## Configuration Methods + +### Method 1: Automatic Configuration (Environment Variable) + +The simplest way to configure Flask backend is using the `VITE_FLASK_BACKEND_URL` environment variable. + +**When to use:** +- Production deployments +- Docker/containerized environments +- When you want to enforce backend usage + +**How it works:** +- App automatically connects to Flask backend on startup +- Manual backend selection is disabled in Settings UI +- Overrides any saved user preferences + +**Setup:** + +Create `.env` file in project root: +```bash +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +Or set in Docker: +```yaml +# docker-compose.yml +services: + frontend: + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 +``` + +Or for Docker build: +```bash +docker build --build-arg VITE_FLASK_BACKEND_URL=http://api.example.com . +``` + +### Method 2: Manual Configuration (Settings Page) + +Users can manually switch backends in the Settings page. + +**When to use:** +- Development/testing +- User preference scenarios +- When Flask backend is optional + +**How it works:** +- Navigate to Settings → Storage Backend +- Select "Flask Backend (Remote Server)" +- Enter Flask backend URL +- Test connection +- Save settings + +**Note:** Manual configuration is automatically disabled when `VITE_FLASK_BACKEND_URL` is set. + +## Backend Deployment Scenarios + +### Scenario 1: Full Docker Stack (Recommended for Production) + +Both frontend and backend in Docker with automatic configuration: + +```bash +docker-compose up -d +``` + +Frontend: `http://localhost:3000` +Backend: `http://localhost:5000` + +The frontend automatically connects to backend via internal Docker network. + +### Scenario 2: Local Development + +Backend in Docker, frontend in dev mode: + +```bash +# Terminal 1: Start backend +docker-compose up backend + +# Terminal 2: Start frontend with env var +echo "VITE_FLASK_BACKEND_URL=http://localhost:5000" > .env +npm run dev +``` + +### Scenario 3: Backend Only + +Run backend separately, users configure manually: + +```bash +cd backend +python app.py +``` + +Users go to Settings and configure `http://localhost:5000` manually. + +### Scenario 4: Remote Backend + +Point frontend to a remote Flask API: + +```bash +# .env +VITE_FLASK_BACKEND_URL=https://api.example.com +``` + +Or configure manually in Settings with the remote URL. + +## Data Migration + +### From IndexedDB to Flask + +1. Ensure Flask backend is running +2. Go to Settings → Storage Backend +3. Select "Flask Backend" +4. Enter backend URL and test connection +5. Click "Migrate IndexedDB Data to Flask" +6. Save storage settings + +### From Flask to IndexedDB + +1. Ensure you have Flask backend URL configured +2. Go to Settings → Storage Backend +3. Click "Migrate Flask Data to IndexedDB" +4. Select "IndexedDB (Local Browser Storage)" +5. Save storage settings + +**Note:** Migration copies data, it doesn't move it. Original data remains in the source. + +## Environment Variable Reference + +| Variable | Description | Default | Example | +|----------|-------------|---------|---------| +| `VITE_FLASK_BACKEND_URL` | Flask backend URL. When set, forces Flask backend usage. | (none) | `http://localhost:5000` | + +## Troubleshooting + +### "Connection failed" error + +**Causes:** +- Backend server not running +- Incorrect URL +- CORS issues +- Network/firewall blocking + +**Solutions:** +1. Verify backend is running: `curl http://localhost:5000/health` +2. Check URL spelling and port number +3. Review backend logs for errors +4. Ensure CORS is enabled in Flask app + +### Environment variable not working + +**Causes:** +- File named incorrectly (must be `.env`) +- Variable not prefixed with `VITE_` +- Server not restarted after change + +**Solutions:** +1. Ensure file is named `.env` (not `.env.local` or `.env.txt`) +2. Restart dev server: `npm run dev` +3. For production builds: rebuild with `npm run build` +4. Verify with: `console.log(import.meta.env.VITE_FLASK_BACKEND_URL)` + +### Settings page is read-only + +This is expected when `VITE_FLASK_BACKEND_URL` is set. To enable manual configuration: +1. Remove the environment variable from `.env` +2. Restart the application +3. Settings will become editable + +### Data not syncing between devices + +Ensure: +1. All devices are configured to use the same Flask backend URL +2. Backend server is accessible from all devices (not localhost if remote) +3. Backend has persistent storage (volume mounted in Docker) + +## Security Considerations + +### Production Deployment + +1. **Use HTTPS:** Always use `https://` URLs in production +2. **Authentication:** Consider adding authentication to Flask backend +3. **CORS:** Configure CORS to allow only your frontend domain +4. **Network:** Run backend in private network, not exposed to internet + +### Example secure configuration: + +```python +# backend/app.py +from flask_cors import CORS + +CORS(app, origins=['https://your-frontend-domain.com']) +``` + +```bash +# .env (production) +VITE_FLASK_BACKEND_URL=https://api.your-domain.com +``` + +## Best Practices + +1. **Development:** Use IndexedDB or local Flask backend +2. **Staging:** Use Flask backend with test data +3. **Production:** Use Flask backend with environment variable +4. **Backup:** Regularly export database from Settings page +5. **Migration:** Test data migration with small dataset first + +## Architecture Diagram + +``` +┌─────────────────────────────────────┐ +│ React Frontend │ +│ │ +│ ┌──────────────────────────────┐ │ +│ │ Storage Config Layer │ │ +│ │ (checks env var first) │ │ +│ └──────────┬───────────────────┘ │ +│ │ │ +│ ┌──────┴──────┐ │ +│ │ │ │ +│ ┌───▼───┐ ┌───▼───────┐ │ +│ │ IDB │ │ Flask │ │ +│ │Adapter│ │ Adapter │ │ +│ └───────┘ └─────┬─────┘ │ +└────────────────────┼───────────────┘ + │ + │ HTTP + │ + ┌──────▼──────┐ + │ Flask │ + │ Backend │ + │ + SQLite │ + └─────────────┘ +``` + +## Additional Resources + +- [Flask Backend README](./backend/README.md) +- [Backend API Documentation](./backend/README.md#api-endpoints) +- [Docker Compose Configuration](./docker-compose.yml) +- [Example .env file](./.env.example) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..82bce5f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Build stage +FROM node:20-alpine AS builder + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . + +ARG VITE_FLASK_BACKEND_URL +ENV VITE_FLASK_BACKEND_URL=$VITE_FLASK_BACKEND_URL + +RUN npm run build + +# Production stage +FROM nginx:alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 3000 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md new file mode 100644 index 0000000..9cb0aac --- /dev/null +++ b/IMPLEMENTATION.md @@ -0,0 +1,202 @@ +# Implementation Summary: Auto Backend Configuration + +## Overview + +Implemented automatic Flask backend configuration via Docker environment variable (`VITE_FLASK_BACKEND_URL`). When set, the application automatically uses the Flask backend instead of IndexedDB, with manual configuration disabled. + +## Changes Made + +### 1. Storage Configuration (`src/lib/storage.ts`) + +**Added:** +- `getDefaultConfig()` function that checks for `VITE_FLASK_BACKEND_URL` environment variable +- Automatic backend selection based on environment variable presence +- Priority: Environment variable > Saved config > Default (IndexedDB) + +**Behavior:** +- If `VITE_FLASK_BACKEND_URL` is set, always use Flask backend +- Environment variable overrides any saved user preferences +- Auto-initializes with Flask adapter when env var is present + +### 2. Database Layer (`src/lib/db.ts`) + +**Added:** +- Auto-load storage config on first database operation +- Persistent config loading with `configLoaded` flag +- Seamless switching between storage backends + +### 3. Settings UI (`src/pages/SettingsPage.tsx`) + +**Added:** +- Environment variable detection and display +- Read-only mode when env var is set +- Status card showing auto-configuration details +- Connection status indicator +- Disabled form inputs when env var controls backend + +**Features:** +- Visual indicator for auto-configured backend +- Shows current backend URL from env var +- Displays configuration source +- Test connection button for auto-configured backends + +### 4. Visual Indicators (`src/components/BackendIndicator.tsx`) + +**Added:** +- Header badge showing active storage backend +- "Local" badge for IndexedDB +- "Backend" badge with dot indicator for auto-configured Flask +- Tooltips explaining storage type + +### 5. TypeScript Definitions (`src/vite-end.d.ts`) + +**Added:** +- Type definitions for `VITE_FLASK_BACKEND_URL` +- Proper `ImportMetaEnv` interface + +### 6. Docker Configuration + +**Added:** +- `Dockerfile` - Multi-stage build for production frontend +- `nginx.conf` - Nginx configuration with API proxy +- `.dockerignore` - Optimized Docker builds +- Updated `docker-compose.yml` - Full stack with auto-configuration +- `docker-compose.backend-only.yml` - Backend-only deployment + +**Features:** +- Frontend and backend containers +- Automatic environment variable passing +- Persistent data volumes +- Build-time and runtime env var support + +### 7. Documentation + +**Created:** +- `.env.example` - Environment variable template +- `QUICKSTART.md` - Quick start guide for all scenarios +- `BACKEND-CONFIG.md` - Comprehensive backend configuration guide +- `docker-compose.README.md` - Docker deployment examples +- Updated `README.md` - New main readme with features +- Updated `README-APP.md` - Enhanced with env var docs +- Updated `backend/README.md` - Auto-configuration instructions + +**Documentation covers:** +- Environment variable usage +- Multiple deployment scenarios +- Docker configurations +- Manual vs automatic configuration +- Troubleshooting guide +- Migration procedures +- Security considerations + +## Configuration Methods + +### Method 1: Environment Variable (Automatic) + +```bash +# .env file +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +**Result:** App automatically uses Flask backend, Settings locked + +### Method 2: Docker Compose + +```yaml +services: + frontend: + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 +``` + +**Result:** Full stack with auto-configured backend + +### Method 3: Manual (Settings Page) + +Navigate to Settings → Select Flask Backend → Enter URL → Save + +**Result:** User-controlled backend selection + +## Priority Order + +1. **Environment Variable** (`VITE_FLASK_BACKEND_URL`) - Highest priority +2. **Saved User Preference** (localStorage) +3. **Default** (IndexedDB) + +## User Experience + +### With Environment Variable Set: + +1. App starts and detects `VITE_FLASK_BACKEND_URL` +2. Automatically initializes Flask backend adapter +3. Shows "Backend" badge in header (with dot indicator) +4. Settings page displays auto-configuration card +5. Backend selection controls are disabled +6. "Save Storage Settings" button is disabled + +### Without Environment Variable: + +1. App starts with default IndexedDB +2. Shows "Local" badge in header +3. Settings page allows backend selection +4. Users can manually configure Flask backend +5. All controls are enabled + +## Testing Scenarios + +### Scenario 1: Development with Local Backend +```bash +echo "VITE_FLASK_BACKEND_URL=http://localhost:5000" > .env +docker-compose up backend +npm run dev +``` + +### Scenario 2: Full Docker Stack +```bash +docker-compose up -d +# Access at http://localhost:3000 +``` + +### Scenario 3: Local Storage Only +```bash +npm run dev +# No env var, uses IndexedDB +``` + +### Scenario 4: Remote Backend +```bash +echo "VITE_FLASK_BACKEND_URL=https://api.example.com" > .env +npm run dev +``` + +## Key Benefits + +1. **Production Ready:** Environment variable ensures consistent backend usage +2. **Developer Friendly:** Easy local development with auto-configuration +3. **Docker Native:** Seamless integration with container orchestration +4. **User Choice:** Manual configuration still available when needed +5. **Clear Feedback:** UI clearly shows which backend is active +6. **Zero Config:** Full stack works out of the box with docker-compose + +## Backwards Compatibility + +- Existing apps without env var continue using saved preferences +- Manual configuration still works when env var not set +- No breaking changes to existing functionality +- Data migration tools remain functional + +## Security Considerations + +- Environment variables not exposed to client (compile-time only) +- CORS configured in Flask backend +- HTTPS recommended for production +- No credentials stored in environment variables + +## Future Enhancements + +Potential improvements: +- Add backend health check on startup +- Show connection quality indicator +- Support multiple backend URLs for failover +- Add authentication token via env var +- Implement read-only mode configuration diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..46c0e87 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,267 @@ +# Quick Start Guide + +## Choose Your Setup + +### 🚀 Full Stack with Docker (Easiest) + +Everything runs in Docker with automatic backend configuration. + +```bash +docker-compose up -d +``` + +✅ Frontend: http://localhost:3000 +✅ Backend: http://localhost:5000 +✅ Auto-configured to use Flask backend + +--- + +### 💻 Local Development + +Backend in Docker, frontend in development mode. + +```bash +# Terminal 1: Start backend +docker-compose -f docker-compose.backend-only.yml up -d + +# Terminal 2: Configure and start frontend +echo "VITE_FLASK_BACKEND_URL=http://localhost:5000" > .env +npm install +npm run dev +``` + +✅ Frontend: http://localhost:5173 (Vite dev server) +✅ Backend: http://localhost:5000 +✅ Auto-configured to use Flask backend + +--- + +### 🌐 Frontend Only (Local Storage) + +No backend required - uses browser IndexedDB. + +```bash +npm install +npm run dev +``` + +✅ Frontend: http://localhost:5173 +✅ Data stored locally in browser +✅ No server needed + +--- + +### ⚙️ Backend Only + +Run backend separately, configure frontend manually. + +```bash +cd backend +pip install -r requirements.txt +python app.py +``` + +Then in a separate terminal: +```bash +npm install +npm run dev +``` + +✅ Backend: http://localhost:5000 +✅ Frontend: http://localhost:5173 +⚠️ Must configure backend URL in Settings page + +--- + +## Key Features by Setup + +| Feature | Full Stack Docker | Local Dev | Frontend Only | Backend Only | +|---------|------------------|-----------|---------------|--------------| +| Auto-configured backend | ✅ | ✅ | ❌ | ❌ | +| Hot reload | ❌ | ✅ | ✅ | ✅ | +| Multi-device sync | ✅ | ✅ | ❌ | ✅* | +| No dependencies | ❌ | ❌ | ✅ | ❌ | +| Production-ready | ✅ | ❌ | ❌ | ⚠️ | + +*Requires manual configuration + +--- + +## Environment Variables + +### `VITE_FLASK_BACKEND_URL` + +**What it does:** +Automatically configures the app to use a Flask backend instead of IndexedDB. + +**When set:** +- App connects to Flask backend on startup +- Settings page backend selection is disabled +- Overrides any manual configuration + +**Examples:** + +Local backend: +```bash +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +Docker internal: +```bash +VITE_FLASK_BACKEND_URL=http://backend:5000 +``` + +Remote backend: +```bash +VITE_FLASK_BACKEND_URL=https://api.example.com +``` + +**Setup methods:** + +`.env` file: +```bash +echo "VITE_FLASK_BACKEND_URL=http://localhost:5000" > .env +``` + +Docker Compose: +```yaml +services: + frontend: + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 +``` + +Docker build: +```bash +docker build --build-arg VITE_FLASK_BACKEND_URL=http://api.example.com . +``` + +--- + +## Common Commands + +### Docker + +```bash +# Start all services +docker-compose up -d + +# Stop all services +docker-compose down + +# View logs +docker-compose logs -f + +# Rebuild after code changes +docker-compose up -d --build + +# Start backend only +docker-compose -f docker-compose.backend-only.yml up -d +``` + +### NPM + +```bash +# Install dependencies +npm install + +# Development server +npm run dev + +# Production build +npm run build + +# Preview production build +npm run preview +``` + +### Backend (Python) + +```bash +cd backend + +# Install dependencies +pip install -r requirements.txt + +# Run server +python app.py + +# Run with custom database path +DB_PATH=/custom/path/snippets.db python app.py +``` + +--- + +## Troubleshooting + +### "Connection failed" in Settings + +**Problem:** Can't connect to Flask backend + +**Solutions:** +1. Verify backend is running: `curl http://localhost:5000/health` +2. Check URL is correct (include `http://`) +3. Ensure no firewall is blocking port 5000 +4. Check backend logs: `docker-compose logs backend` + +### Environment variable not working + +**Problem:** `VITE_FLASK_BACKEND_URL` not taking effect + +**Solutions:** +1. Restart dev server after creating/modifying `.env` +2. Ensure file is named `.env` (not `.env.txt`) +3. Variable must start with `VITE_` +4. For production builds: rebuild with `npm run build` + +### Settings page is read-only + +**This is expected** when `VITE_FLASK_BACKEND_URL` is set. + +**To enable manual configuration:** +1. Remove the variable from `.env` +2. Restart the application + +### Port already in use + +**Problem:** "Port 3000 (or 5000) is already in use" + +**Solutions:** + +Change frontend port: +```yaml +# docker-compose.yml +services: + frontend: + ports: + - "8080:3000" # Access at http://localhost:8080 +``` + +Change backend port: +```yaml +# docker-compose.yml +services: + backend: + ports: + - "8000:5000" # Access at http://localhost:8000 + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 # Keep internal port same +``` + +Or stop the conflicting service: +```bash +# Find process using port +lsof -i :3000 + +# Kill process (replace PID) +kill -9 +``` + +--- + +## Next Steps + +- 📖 [Full documentation](./README-APP.md) +- 🔧 [Backend configuration guide](./BACKEND-CONFIG.md) +- 🐳 [Docker examples](./docker-compose.README.md) +- 🚀 [Backend API docs](./backend/README.md) diff --git a/README-APP.md b/README-APP.md index 3f69e74..79a0cb4 100644 --- a/README-APP.md +++ b/README-APP.md @@ -34,6 +34,8 @@ CodeSnippet offers flexible data storage with two backend options: ### Switching Storage Backends +#### Manual Configuration + Visit the **Settings** page to: - Choose between IndexedDB and Flask backend - Configure Flask backend URL @@ -42,6 +44,31 @@ Visit the **Settings** page to: - View database statistics - Export/import database backups +#### Automatic Configuration with Environment Variable + +You can automatically configure the Flask backend using a Docker environment variable. When `VITE_FLASK_BACKEND_URL` is set, the app will: +- Automatically use the Flask backend instead of IndexedDB +- Override any manual configuration +- Disable manual backend selection in the Settings page + +**Setup:** + +1. Create a `.env` file in the project root: +```bash +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +2. Or set it in your Docker environment: +```yaml +# docker-compose.yml +services: + frontend: + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 +``` + +**Note:** When the environment variable is set, the storage backend configuration in Settings becomes read-only. To change backends, remove the environment variable and restart the application. + ## Backend Setup ### Running Flask Backend Locally @@ -54,7 +81,24 @@ python app.py Server runs on `http://localhost:5000` by default. -### Running with Docker +### Running with Docker Compose (Full Stack) + +The easiest way to run both frontend and backend with automatic Flask backend configuration: + +```bash +# Start both frontend and backend +docker-compose up -d + +# View logs +docker-compose logs -f + +# Stop services +docker-compose down +``` + +Access the app at `http://localhost:3000`. The frontend is automatically configured to use the Flask backend at `http://backend:5000`. + +### Running Backend Only with Docker Build and run: ```bash @@ -62,11 +106,30 @@ docker build -t codesnippet-backend ./backend docker run -p 5000:5000 -v $(pwd)/data:/data codesnippet-backend ``` -Or use docker-compose: -```bash -docker-compose up -d +Then configure the frontend manually in Settings to use `http://localhost:5000`. + +### Environment Variable Configuration + +When deploying, you can set the `VITE_FLASK_BACKEND_URL` environment variable to automatically configure the Flask backend: + +**For Docker Compose:** +```yaml +services: + frontend: + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 ``` +**For Local Development (.env file):** +```bash +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +When this variable is set: +- The app automatically uses Flask backend instead of IndexedDB +- Manual backend configuration in Settings is disabled +- Perfect for production deployments where backend is always available + ### Backend API The Flask backend provides a REST API: diff --git a/README.md b/README.md index 358beec..2a04e31 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,95 @@ -# ✨ Welcome to Your Spark Template! -You've just launched your brand-new Spark Template Codespace — everything’s fired up and ready for you to explore, build, and create with Spark! +# CodeSnippet - Code Snippet Manager -This template is your blank canvas. It comes with a minimal setup to help you get started quickly with Spark development. +A powerful code snippet management application with flexible storage backends and an integrated component library showcase. -🚀 What's Inside? -- A clean, minimal Spark environment -- Pre-configured for local development -- Ready to scale with your ideas - -🧠 What Can You Do? +## 🚀 Quick Start -Right now, this is just a starting point — the perfect place to begin building and testing your Spark applications. +Choose the setup that works best for you: -🧹 Just Exploring? -No problem! If you were just checking things out and don’t need to keep this code: +### Option 1: Full Stack with Docker (Recommended) +```bash +docker-compose up -d +``` +Access at: http://localhost:3000 (auto-configured with Flask backend) -- Simply delete your Spark. -- Everything will be cleaned up — no traces left behind. +### Option 2: Local Development +```bash +# Start backend +docker-compose -f docker-compose.backend-only.yml up -d -📄 License For Spark Template Resources +# Configure frontend +echo "VITE_FLASK_BACKEND_URL=http://localhost:5000" > .env + +# Start frontend +npm install +npm run dev +``` +Access at: http://localhost:5173 + +### Option 3: Frontend Only (No Backend) +```bash +npm install +npm run dev +``` +Access at: http://localhost:5173 (uses local IndexedDB storage) + +📖 **[See detailed setup instructions →](./QUICKSTART.md)** + +## 🔑 Key Features + +- 📝 **Snippet Management** - Create, edit, and organize code snippets with syntax highlighting +- 🔍 **Smart Search** - Real-time search across title, description, language, and code +- 👁️ **Live Preview** - Split-screen editor with live React component preview +- 💾 **Flexible Storage** - Choose between local IndexedDB or Flask backend +- 🔄 **Auto-Configuration** - Automatically use Flask backend via environment variable +- 🗂️ **Component Library** - Showcase organized by atomic design principles +- 📤 **Export/Import** - Backup and restore your entire database +- 🎨 **Beautiful UI** - Modern dark theme with purple and cyan accents + +## 🎯 Storage Backends + +CodeSnippet supports two storage backends: + +### IndexedDB (Default) +- Local browser storage +- No server required +- Perfect for personal use + +### Flask Backend (Optional) +- Remote server storage +- Multi-device sync +- Requires Flask backend + +**🔧 Auto-Configuration:** +Set `VITE_FLASK_BACKEND_URL` environment variable to automatically use Flask backend: + +```bash +# .env file +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +When set, the app automatically connects to Flask backend and disables manual configuration. + +📖 **[Complete backend configuration guide →](./BACKEND-CONFIG.md)** + +## 📚 Documentation + +- **[Quick Start Guide](./QUICKSTART.md)** - Get up and running quickly +- **[Application Guide](./README-APP.md)** - Features and usage +- **[Backend Configuration](./BACKEND-CONFIG.md)** - Detailed backend setup +- **[Backend API](./backend/README.md)** - Flask API documentation +- **[Docker Examples](./docker-compose.README.md)** - Docker deployment options + +## 🛠️ Technology Stack + +- React 19 + TypeScript +- SQL.js (SQLite in WebAssembly) +- Flask (Python backend) +- Monaco Editor (VS Code editor) +- Framer Motion (animations) +- Shadcn UI (component library) +- Tailwind CSS (styling) + +## 📄 License The Spark Template files and resources from GitHub are licensed under the terms of the MIT license, Copyright GitHub, Inc. diff --git a/backend/README.md b/backend/README.md index 293487a..423869c 100644 --- a/backend/README.md +++ b/backend/README.md @@ -67,6 +67,30 @@ Default: `/data/snippets.db` ## Frontend Integration +### Automatic Configuration (Recommended) + +The frontend can be automatically configured to use the Flask backend via environment variable: + +**For Docker Compose (full stack):** +```bash +docker-compose up -d +``` + +The frontend will automatically connect to the backend at `http://backend:5000`. + +**For local development:** +```bash +# .env file in project root +VITE_FLASK_BACKEND_URL=http://localhost:5000 +``` + +When `VITE_FLASK_BACKEND_URL` is set: +- Frontend automatically uses Flask backend +- Manual backend selection in Settings is disabled +- Perfect for production deployments + +### Manual Configuration + In the CodeSnippet app: 1. Navigate to Settings page 2. Select "Flask Backend (Remote Server)" @@ -75,6 +99,8 @@ In the CodeSnippet app: 5. Click "Save Storage Settings" 6. Optionally migrate existing IndexedDB data to Flask +See [BACKEND-CONFIG.md](../BACKEND-CONFIG.md) for detailed configuration guide. + ## Docker Details ### Building the Image diff --git a/docker-compose.README.md b/docker-compose.README.md new file mode 100644 index 0000000..bad0ba1 --- /dev/null +++ b/docker-compose.README.md @@ -0,0 +1,71 @@ +# Docker Compose Examples + +This directory contains example Docker Compose configurations for different deployment scenarios. + +## Files + +- `docker-compose.yml` - Default full stack with auto-configured backend +- `docker-compose.backend-only.yml` - Backend service only +- `docker-compose.dev.yml` - Development setup with hot reload + +## Usage + +### Full Stack (Frontend + Backend) + +```bash +docker-compose up -d +``` + +Access: +- Frontend: http://localhost:3000 +- Backend API: http://localhost:5000 + +### Backend Only + +```bash +docker-compose -f docker-compose.backend-only.yml up -d +``` + +Access: +- Backend API: http://localhost:5000 + +Then run frontend locally: +```bash +npm run dev +``` + +Configure frontend manually in Settings to use `http://localhost:5000`. + +### Development Mode + +```bash +docker-compose -f docker-compose.dev.yml up -d +``` + +This runs: +- Backend in Docker +- Frontend expects you to run `npm run dev` locally with env var set + +## Environment Variables + +All configurations support these environment variables: + +### Backend +- `DB_PATH` - SQLite database path (default: `/data/snippets.db`) + +### Frontend +- `VITE_FLASK_BACKEND_URL` - Flask backend URL (enables auto-configuration) + +## Persistence + +All configurations use a Docker volume `snippet-data` for persistent storage. + +To backup: +```bash +docker run --rm -v codesnippet_snippet-data:/data -v $(pwd):/backup alpine tar czf /backup/snippets-backup.tar.gz /data +``` + +To restore: +```bash +docker run --rm -v codesnippet_snippet-data:/data -v $(pwd):/backup alpine tar xzf /backup/snippets-backup.tar.gz -C / +``` diff --git a/docker-compose.backend-only.yml b/docker-compose.backend-only.yml new file mode 100644 index 0000000..4f3e878 --- /dev/null +++ b/docker-compose.backend-only.yml @@ -0,0 +1,15 @@ +version: '3.8' + +services: + backend: + build: ./backend + ports: + - "5000:5000" + volumes: + - snippet-data:/data + environment: + - DB_PATH=/data/snippets.db + restart: unless-stopped + +volumes: + snippet-data: diff --git a/docker-compose.yml b/docker-compose.yml index 4f3e878..76172c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,5 +11,18 @@ services: - DB_PATH=/data/snippets.db restart: unless-stopped + frontend: + build: + context: . + args: + - VITE_FLASK_BACKEND_URL=http://localhost:5000 + ports: + - "3000:3000" + environment: + - VITE_FLASK_BACKEND_URL=http://backend:5000 + depends_on: + - backend + restart: unless-stopped + volumes: snippet-data: diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..10f81be --- /dev/null +++ b/nginx.conf @@ -0,0 +1,19 @@ +server { + listen 3000; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_pass http://backend:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/src/App.tsx b/src/App.tsx index 14e61c6..aed4165 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom' import { motion } from 'framer-motion' import { Code } from '@phosphor-icons/react' import { Navigation, NavigationProvider, NavigationSidebar, useNavigation } from '@/components/Navigation' +import { BackendIndicator } from '@/components/BackendIndicator' import { HomePage } from '@/pages/HomePage' import { DemoPage } from '@/pages/DemoPage' import { AtomsPage } from '@/pages/AtomsPage' @@ -62,6 +63,13 @@ function AppContent() { CodeSnippet + + + diff --git a/src/components/BackendIndicator.tsx b/src/components/BackendIndicator.tsx new file mode 100644 index 0000000..c058a0a --- /dev/null +++ b/src/components/BackendIndicator.tsx @@ -0,0 +1,53 @@ +import { useState, useEffect } from 'react' +import { Database, CloudCheck } from '@phosphor-icons/react' +import { getStorageConfig } from '@/lib/storage' +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' + +export function BackendIndicator() { + const [backend, setBackend] = useState<'indexeddb' | 'flask'>('indexeddb') + const [isEnvConfigured, setIsEnvConfigured] = useState(false) + + useEffect(() => { + const config = getStorageConfig() + setBackend(config.backend) + setIsEnvConfigured(Boolean(import.meta.env.VITE_FLASK_BACKEND_URL)) + }, []) + + if (backend === 'indexeddb') { + return ( + + + +
+ + Local +
+
+ +

Using IndexedDB (Local Storage)

+
+
+
+ ) + } + + return ( + + + +
+ + Backend + {isEnvConfigured && ( + + )} +
+
+ +

Using Flask Backend

+ {isEnvConfigured &&

Auto-configured

} +
+
+
+ ) +} diff --git a/src/lib/db.ts b/src/lib/db.ts index f762da9..e559a71 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -1,10 +1,11 @@ import initSqlJs, { Database } from 'sql.js' import type { Snippet, SnippetTemplate } from './types' -import { getStorageConfig, FlaskStorageAdapter } from './storage' +import { getStorageConfig, FlaskStorageAdapter, loadStorageConfig } from './storage' let dbInstance: Database | null = null let sqlInstance: any = null let flaskAdapter: FlaskStorageAdapter | null = null +let configLoaded = false const DB_KEY = 'codesnippet-db' const IDB_NAME = 'CodeSnippetDB' @@ -195,6 +196,11 @@ async function saveDB() { } function getFlaskAdapter(): FlaskStorageAdapter | null { + if (!configLoaded) { + loadStorageConfig() + configLoaded = true + } + const config = getStorageConfig() if (config.backend === 'flask' && config.flaskUrl) { if (!flaskAdapter || flaskAdapter['baseUrl'] !== config.flaskUrl) { diff --git a/src/lib/storage.ts b/src/lib/storage.ts index d5e5f69..10f22a6 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -7,13 +7,33 @@ export interface StorageConfig { flaskUrl?: string } -let currentConfig: StorageConfig = { - backend: 'indexeddb' -} - const STORAGE_CONFIG_KEY = 'codesnippet-storage-config' +function getDefaultConfig(): StorageConfig { + const flaskUrl = import.meta.env.VITE_FLASK_BACKEND_URL + + if (flaskUrl) { + return { + backend: 'flask', + flaskUrl: flaskUrl + } + } + + return { + backend: 'indexeddb' + } +} + +let currentConfig: StorageConfig = getDefaultConfig() + export function loadStorageConfig(): StorageConfig { + const defaultConfig = getDefaultConfig() + + if (defaultConfig.backend === 'flask' && defaultConfig.flaskUrl) { + currentConfig = defaultConfig + return currentConfig + } + try { const saved = localStorage.getItem(STORAGE_CONFIG_KEY) if (saved) { diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index ea6e6a8..f226157 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -29,6 +29,7 @@ export function SettingsPage() { const [flaskUrl, setFlaskUrl] = useState('') const [flaskConnectionStatus, setFlaskConnectionStatus] = useState<'unknown' | 'connected' | 'failed'>('unknown') const [testingConnection, setTestingConnection] = useState(false) + const [envVarSet, setEnvVarSet] = useState(false) const loadStats = async () => { setLoading(true) @@ -62,8 +63,13 @@ export function SettingsPage() { useEffect(() => { loadStats() const config = loadStorageConfig() + + const envFlaskUrl = import.meta.env.VITE_FLASK_BACKEND_URL + const isEnvSet = Boolean(envFlaskUrl) + setEnvVarSet(isEnvSet) + setStorageBackend(config.backend) - setFlaskUrl(config.flaskUrl || 'http://localhost:5000') + setFlaskUrl(config.flaskUrl || envFlaskUrl || 'http://localhost:5000') if (config.backend === 'flask' && config.flaskUrl) { testFlaskConnection(config.flaskUrl) } @@ -244,6 +250,57 @@ export function SettingsPage() {
+ {envVarSet && ( + + + + + Backend Auto-Configured + + + Flask backend is configured via environment variable + + + +
+
+ Backend URL + {flaskUrl} +
+
+ Configuration Source + VITE_FLASK_BACKEND_URL +
+
+ Status + {flaskConnectionStatus === 'connected' && ( + + + Connected + + )} + {flaskConnectionStatus === 'failed' && ( + + + Connection Failed + + )} + {flaskConnectionStatus === 'unknown' && ( + + )} +
+
+
+
+ )} + @@ -255,11 +312,26 @@ export function SettingsPage() { - setStorageBackend(value as StorageBackend)}> + {envVarSet && ( + + + + + Storage backend is configured via VITE_FLASK_BACKEND_URL environment variable and cannot be changed here. + + + + )} + + setStorageBackend(value as StorageBackend)} + disabled={envVarSet} + >
- +
-
- +
-