diff --git a/Dockerfile b/Dockerfile index d12b80e..ffaefda 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,9 @@ ARG USE_FRONTEND_BACKUP RUN if [ "$USE_FRONTEND_BACKUP" = "true" ]; then \ rm -rf /app/frontend && mkdir -p /app/frontend && cp -R /app/frontend-backup/. /app/frontend/; \ else \ - cd frontend-src && npm install && npm run build; \ + cd frontend-src && npm install && npm run build && \ + mkdir -p /app/frontend/plugins && \ + echo "Plugins directory created for frontend build"; \ fi # Create login.html from join.html if it doesn't exist @@ -65,7 +67,7 @@ RUN pnpm db:generate # Copy built application from builder stage COPY --from=builder /app/dist ./dist -# Copy built frontend from builder stage +# Copy built frontend from builder stage (includes SDK and plugins directory) COPY --from=builder /app/frontend ./frontend # Expose port diff --git a/PLUGINS.md b/PLUGINS.md new file mode 100644 index 0000000..9c0f9ac --- /dev/null +++ b/PLUGINS.md @@ -0,0 +1,125 @@ +# FurryPlace Plugins System + +The FurryPlace SDK provides an extensible plugin system that allows you to add custom buttons and functionality to the UI without modifying the core codebase. + +## Quick Start + +### Development (Local) + +1. Add your plugin file to `frontend-backup/plugins/`: + ```bash + # Example: Create a custom button plugin + cat > frontend-backup/plugins/my-plugin.js << 'EOF' + (function() { + function waitForSDK(callback) { + if (window.FurryPlaceSDK) { + callback(); + } else { + setTimeout(() => waitForSDK(callback), 100); + } + } + + waitForSDK(() => { + window.FurryPlaceSDK.registerButton({ + id: 'my-button', + title: 'My Custom Button', + position: 'bottom', + icon: '...', + onClick: () => alert('Clicked!') + }); + }); + })(); + EOF + ``` + +2. Refresh your browser - the plugin loads automatically! + +### Production (Docker) + +When using `USE_FRONTEND_BACKUP=true`: + +1. **Before building the Docker image**, add plugins to `frontend-backup/plugins/` +2. Build the image: + ```bash + docker build --build-arg USE_FRONTEND_BACKUP=true -t furryplace . + ``` +3. The plugins will be included in the image automatically + +When using the regular frontend build (not `USE_FRONTEND_BACKUP`): + +1. Create a `frontend-src/public/plugins/` directory +2. Add your plugin files there +3. Build normally - the plugins will be copied to the final build + +### Runtime Plugin Loading (Docker Volume) + +You can also mount a plugins directory at runtime to add/update plugins without rebuilding: + +```bash +docker run -d \ + -v ./my-plugins:/app/frontend/plugins \ + -e USE_FRONTEND_BACKUP=false \ + furryplace +``` + +Or with docker-compose: + +```yaml +services: + furryplace: + image: furryplace + volumes: + - ./my-plugins:/app/frontend/plugins + environment: + USE_FRONTEND_BACKUP: "false" +``` + +## How It Works + +1. **Backend**: The `/api/plugins` endpoint (in `src/routes/plugins.ts`) scans the plugins directory and returns a list of `.js` files +2. **Frontend**: The SDK (`furryplace-sdk.js`) automatically fetches this list and dynamically loads each plugin +3. **Plugins**: Each plugin registers buttons or functionality using the SDK API + +## Plugin Development + +See the full documentation in [frontend-backup/plugins/README.md](frontend-backup/plugins/README.md) for: +- SDK API reference +- Button configuration options +- Example plugins +- Troubleshooting tips + +## Environment Variables + +The plugin system respects the `USE_FRONTEND_BACKUP` environment variable: +- `USE_FRONTEND_BACKUP=true` → Loads from `frontend-backup/plugins/` +- `USE_FRONTEND_BACKUP=false` → Loads from `frontend/plugins/` + +This is automatically handled by the backend routes. + +## Disabling Plugins + +To disable a plugin without deleting it: +1. Rename it to anything that doesn't end in `.js` (e.g., `my-plugin.js.disabled`) +2. Refresh the page + +The SDK only loads files ending in `.js`. + +## Security Notes + +- Plugins have full access to the browser's JavaScript environment +- Only load plugins from trusted sources +- Consider reviewing plugin code before deployment +- Plugins run in the same origin as your application + +## Examples + +Example plugins are included in `frontend-backup/plugins/example-button.js`: +- Help button with tooltip +- Debug info button +- Conditional rendering example +- External link button (Discord) + +To try them out: +1. The example plugin is automatically loaded +2. Check the browser console for loading messages +3. Look for the new buttons in the UI diff --git a/frontend-backup/_app/immutable/entry/app.DTM8GXam.js b/frontend-backup/_app/immutable/entry/app.DTM8GXam.js index bd6140b..bb6c43e 100644 --- a/frontend-backup/_app/immutable/entry/app.DTM8GXam.js +++ b/frontend-backup/_app/immutable/entry/app.DTM8GXam.js @@ -29,7 +29,7 @@ const __vite__mapDeps = ( "../chunks/D3yDgRbd.js", "../chunks/wZ7b5CwQ.js", "../nodes/3.DOMAwJeg.js", - "../nodes/4.DB4WphWP.js", + "../nodes/4.CrDfIbdR.js", "../chunks/DueIxFLX.js", "../chunks/CgCA7Awo.js", "../chunks/Dpga8uG-.js", @@ -6133,7 +6133,7 @@ const Ll = ai(gl), ), () => L( - () => import("../nodes/4.DB4WphWP.js"), + () => import("../nodes/4.CrDfIbdR.js"), __vite__mapDeps([ 26, 1, 2, 3, 4, 5, 10, 12, 22, 11, 20, 19, 6, 7, 8, 9, 27, 13, 28, 29, 30, 31, 32, 33, 34, 24, 35, 36, 37, 38, 39, 40, 15, 18, 23, 14, 41, diff --git a/frontend-backup/plugins/.gitignore b/frontend-backup/plugins/.gitignore new file mode 100644 index 0000000..2291e69 --- /dev/null +++ b/frontend-backup/plugins/.gitignore @@ -0,0 +1,5 @@ +# Ignore all plugin files except the example +* +!.gitignore +!README.md +!example-button.js diff --git a/rename-i18n-variables.js b/rename-i18n-variables.js index c0f99f0..07e14c2 100644 --- a/rename-i18n-variables.js +++ b/rename-i18n-variables.js @@ -1,7 +1,7 @@ const fs = require('fs'); const path = require('path'); -const filePath = 'f:\\place\\openplace\\frontend-backup\\_app\\immutable\\nodes\\4.CrDfIbdR.js'; +const filePath = 'f:\\place\\FurryPlace\\frontend-backup\\_app\\immutable\\nodes\\4.CrDfIbdR.js'; // Read the file let content = fs.readFileSync(filePath, 'utf8'); diff --git a/src/routes/plugins.ts b/src/routes/plugins.ts index ca9fd44..6020d8f 100644 --- a/src/routes/plugins.ts +++ b/src/routes/plugins.ts @@ -6,11 +6,14 @@ import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +// Determine which frontend directory to use (matches index.ts logic) +const frontendDir = process.env['USE_FRONTEND_BACKUP'] === 'true' ? 'frontend-backup' : 'frontend'; + export function setupPluginRoutes(app: App) { // Public endpoint - Get list of available plugins app.get('/api/plugins', async (_req, res) => { try { - const pluginsDir = path.join(__dirname, '..', '..', 'frontend-backup', 'plugins'); + const pluginsDir = path.join(__dirname, '..', '..', frontendDir, 'plugins'); // Check if plugins directory exists if (!fs.existsSync(pluginsDir)) {