') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Add Coolify deployment instructions by reprewindai-dev · Pull Request #3 · reprewindai-dev/cAPI · GitHub
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
20 changes: 20 additions & 0 deletions DEPLOYMENT.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
# Deploying to Coolify on Hetzner

This project is fully ready to be deployed to a Coolify instance (e.g., hosted on Hetzner) using the provided `Dockerfile` or Nixpacks.

## Option 1: Docker (Recommended)
Coolify can automatically detect the `Dockerfile` at the root of the repository.

1. Connect your repository to your Coolify instance.
2. Create a new Resource in Coolify and select **Project / Application**.
3. Choose the repository and branch.
4. Coolify will auto-detect the configuration. Under the **Build Pack** setting, select **Docker** (it might already be selected).
5. Ensure the **Port** is set to `3000`.
6. Deploy! The `Dockerfile` uses Next.js Standalone mode for a highly optimized, lightweight Node.js production image.

## Option 2: Nixpacks
If you prefer not to use the Dockerfile, Coolify uses Nixpacks by default which works seamlessly with Next.js.
1. When setting up the Application in Coolify, select **Nixpacks** as the build pack.
2. Coolify will automatically detect it as a Next.js application, install dependencies, run `npm run build`, and start it.

*(Note: If you use Nixpacks, you might need to remove `output: "standalone"` from `next.config.mjs` depending on your preference, but it generally works fine either way).*
13 changes: 13 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -78,3 +78,16 @@ The runtime seeds a realistic fleet (agents, capabilities, three-tier policies,
## Stack

Next.js 14 (App Router) · TypeScript · Tailwind CSS · Framer Motion · Node `crypto`. Part of the **Veklom** ecosystem.

## Deployment

This project is fully ready to be deployed to a **Coolify** instance (e.g., hosted on Hetzner) using the provided `Dockerfile` or Nixpacks.

### Deploying to Coolify

1. Connect your repository to your Coolify instance.
2. Create a new Resource in Coolify and select **Project / Application**.
3. Choose the repository and branch.
4. Coolify will auto-detect the configuration. Under the **Build Pack** setting, select **Docker** (it should automatically pick up the `Dockerfile` at the root).
5. Ensure the **Port** is set to `3000`.
6. Deploy! The `Dockerfile` uses Next.js Standalone mode for a highly optimized, lightweight Node.js production image.