Conversation
Major restructure of n8n-hosting repository for Cyclone-S5 workflows ## Changes ### Repository Structure - Rename from n8n-hosting to Cyclone-S5 - Create flat structure: workflows/, config/, utils/, schemas/, scripts/ at root - Move legacy deployment configs to deployment/ folder - Add .gitignore to protect sensitive files ### Configuration - Create comprehensive config/.env.example with all environment variables - Add config/airtable-schemas.json for database structure documentation - Add config/api-endpoints.json for API configuration centralization - Add config/prompt-templates.json for reusable prompt templates ### Helper Scripts - Add utils/n8n-helpers/airtable-ops.js for Airtable CRUD operations - Add utils/n8n-helpers/image-generation.js for fal.ai image generation - Add utils/n8n-helpers/prompt-builder.js for prompt construction - Add utils/n8n-helpers/error-handler.js for retry logic and error handling ### Deployment Scripts - Add scripts/deploy-workflow.sh for workflow deployment to n8n - Add scripts/backup-workflows.sh for workflow backup from n8n - Add scripts/validate-config.js for configuration validation - Add scripts/sync-env.sh for environment template syncing ### TypeScript Schemas - Add schemas/AirtableBase.ts for base Airtable types - Add schemas/AdCopyAnalysis.ts for Ad Copy workflow types - Add schemas/ImageRecord.ts for image generation types - Add schemas/Actor.ts, Product.ts, Scene.ts for supporting tables ### Automation - Add .github/workflows/backup-n8n.yml for automated daily workflow backups ### Documentation - Update README.md with comprehensive Cyclone-S5 documentation - Move workflow files to workflows/ directory - Preserve git history for all moved files BREAKING CHANGE: Repository renamed and restructured. See README.md for new structure and usage. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…g and summary reporting to the backup-n8n.yml script. Updated README to reflect project name change and provide detailed setup instructions for deploying and validating n8n workflows.
…the backup-n8n.yml script with additional error handling and summary reporting features. Updated README to include new instructions for the backup process.
… Enhanced the backup-n8n.yml script with more detailed logging features and refined error handling mechanisms. Updated README to include the latest changes in the backup process.
There was a problem hiding this comment.
Pull request overview
This PR turns the repository into a “Cyclone-S5” toolkit for running and managing n8n-based ad creative generation: it adds n8n workflows (Airtable → fal.ai → Airtable), centralized configuration templates, helper utilities, and deployment/backup automation, plus adds two Next.js sample apps.
Changes:
- Added n8n workflows for batch image generation and supporting documentation.
- Added centralized config (
config/*), reusable helper modules (utils/n8n-helpers/*), and scripts to validate/deploy/backup workflows. - Added deployment templates (Docker Compose / Kubernetes) and removed committed
.envfiles / an old K8s secret manifest.
Reviewed changes
Copilot reviewed 49 out of 81 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| workflows/palmaura-fal-image-generation.json | New hourly/webhook-triggered Airtable→fal.ai image generation workflow with retry/error logging. |
| workflows/gumloop-airtable-mcp.json | Adds Gumloop MCP server configuration for Airtable access. |
| workflows/claude-n8n-http.json | Adds an n8n HTTP Request node example targeting fal.ai queue endpoint. |
| workflows/backups/.gitkeep | Keeps backups directory in git. |
| workflows/README.md | Adds step-by-step instructions for building key n8n workflows. |
| utils/n8n-helpers/prompt-builder.js | Adds JS helpers for building/cleaning/variant-generating prompts. |
| utils/n8n-helpers/image-generation.js | Adds JS helper for calling fal.ai Flux models + validation/error parsing. |
| utils/n8n-helpers/error-handler.js | Adds generic retry/error parsing + optional Airtable error logging helper. |
| utils/n8n-helpers/airtable-ops.js | Adds CRUD helpers for Airtable API operations. |
| statscaler/tsconfig.json | Adds TS config for new Next.js app. |
| statscaler/public/window.svg | Adds static asset. |
| statscaler/public/vercel.svg | Adds static asset. |
| statscaler/public/next.svg | Adds static asset. |
| statscaler/public/globe.svg | Adds static asset. |
| statscaler/public/file.svg | Adds static asset. |
| statscaler/postcss.config.mjs | Adds PostCSS config (Tailwind). |
| statscaler/package.json | Adds Next.js app package manifest. |
| statscaler/next.config.ts | Adds Next.js config stub. |
| statscaler/eslint.config.mjs | Adds ESLint flat config for Next.js. |
| statscaler/app/page.tsx | Adds default Next.js landing page. |
| statscaler/app/layout.tsx | Adds root layout with Geist fonts. |
| statscaler/app/globals.css | Adds Tailwind import + base theme variables. |
| statscaler/app/favicon.ico | Adds favicon. |
| statscaler/README.md | Adds default Next.js README. |
| statscaler/.gitignore | Adds app-specific ignores. |
| scripts/validate-config.js | Adds config/workflow JSON validation script. |
| scripts/sync-env.sh | Adds script to sync env template into deployment folders. |
| scripts/deploy-workflow.sh | Adds script to deploy workflows to n8n via API. |
| scripts/backup-workflows.sh | Adds script to backup workflows from n8n via API. |
| schemas/Scene.ts | Adds TS schema for Scenes table. |
| schemas/Product.ts | Adds TS schema for Products table. |
| schemas/ImageRecord.ts | Adds TS schema for Images table + fal.ai/Bannerbear types. |
| schemas/AirtableBase.ts | Adds base TS types for Airtable records/attachments/queries. |
| schemas/AdCopyAnalysis.ts | Adds TS schema for Ad Copy table + pipeline IO types. |
| schemas/Actor.ts | Adds TS schema for Actors table. |
| kubernetes/postgres-secret.yaml | Removes previously committed K8s Secret manifest with placeholder creds. |
| docker-compose/withPostgresAndWorker/.env | Removes committed env file. |
| docker-compose/withPostgres/.env | Removes committed env file. |
| docker-compose/subfolderWithSSL/.env | Removes committed env file. |
| docker-caddy/.env | Removes committed env file. |
| deployment/kubernetes/postgres-service.yaml | Adds K8s service manifest for Postgres. |
| deployment/kubernetes/postgres-deployment.yaml | Adds K8s Postgres deployment manifest. |
| deployment/kubernetes/postgres-configmap.yaml | Adds K8s ConfigMap containing init script for non-root user setup. |
| deployment/kubernetes/postgres-claim0-persistentvolumeclaim.yaml | Adds PVC for Postgres storage. |
| deployment/kubernetes/namespace.yaml | Adds n8n namespace manifest. |
| deployment/kubernetes/n8n-service.yaml | Adds K8s service manifest for n8n. |
| deployment/kubernetes/n8n-deployment.yaml | Adds K8s deployment manifest for n8n. |
| deployment/kubernetes/n8n-claim0-persistentvolumeclaim.yaml | Adds PVC for n8n data. |
| deployment/kubernetes/README.md | Adds upstream-style K8s hosting README. |
| deployment/kubernetes/LICENSE | Adds MIT license file for the imported hosting configs. |
| deployment/docker-compose/withPostgresAndWorker/init-data.sh | Adds Postgres init script to create non-root DB user. |
| deployment/docker-compose/withPostgresAndWorker/docker-compose.yml | Adds n8n+Postgres+Redis queue-mode compose stack. |
| deployment/docker-compose/withPostgresAndWorker/README.md | Adds compose usage documentation. |
| deployment/docker-compose/withPostgres/init-data.sh | Adds Postgres init script to create non-root DB user. |
| deployment/docker-compose/withPostgres/docker-compose.yml | Adds n8n+Postgres compose stack. |
| deployment/docker-compose/withPostgres/README.md | Adds compose usage documentation. |
| deployment/docker-compose/subfolderWithSSL/docker-compose.yml | Adds Traefik-based subfolder SSL compose template. |
| deployment/docker-compose/subfolderWithSSL/README.md | Adds compose usage documentation. |
| deployment/docker-caddy/local_files/.gitkeep | Keeps local_files directory in git. |
| deployment/docker-caddy/docker-compose.yml | Adds Caddy reverse proxy + n8n compose template. |
| deployment/docker-caddy/caddy_config/Caddyfile | Adds Caddy configuration stub. |
| deployment/docker-caddy/caddy_config/.gitkeep | Keeps caddy_config dir in git. |
| deployment/docker-caddy/README.md | Adds upstream-style Docker+Caddy README. |
| deployment/docker-caddy/LICENSE | Adds MIT license file for the imported hosting configs. |
| config/prompt-templates.json | Adds reusable prompt templates and prompt-generation templates. |
| config/api-endpoints.json | Adds centralized API endpoint config for fal/bannerbear/airtable/openai. |
| config/airtable-schemas.json | Adds centralized Airtable table/field schema mapping. |
| config/.env.example | Adds consolidated env var template for n8n + services + scripts. |
| clerk-nextjs-app/tsconfig.json | Adds TS config for Clerk+Next.js app. |
| clerk-nextjs-app/src/proxy.ts | Adds Clerk middleware. |
| clerk-nextjs-app/src/app/page.tsx | Adds Clerk demo landing page. |
| clerk-nextjs-app/src/app/layout.tsx | Adds ClerkProvider layout + auth buttons. |
| clerk-nextjs-app/src/app/globals.css | Adds styling for Clerk demo app. |
| clerk-nextjs-app/package.json | Adds Clerk+Next.js app dependencies. |
| clerk-nextjs-app/next.config.ts | Adds Next.js config stub. |
| clerk-nextjs-app/README.md | Adds Clerk template documentation. |
| clerk-nextjs-app/.gitignore | Adds app-specific ignores. |
| README.md | Replaces root README with Cyclone-S5 documentation and usage guides. |
| .gitignore | Adds repo-wide ignores for env/secrets/n8n data/workflow backups. |
| .github/workflows/backup-n8n.yml | Adds GitHub Action to back up n8n workflows on a schedule. |
| .claude/settings.local.json | Adds local tool permissions configuration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "mcp-remote@0.1.12", | ||
| "https://mcp.gumloop.com/airtable/Po4tsiByVANmPe33wJygwM6qNJG3:d965ea51425a4c7e9c15f5d3b21088c3:eyJleHRlcm5hbF9jbGllbnQiOnRydWV9/mcp" | ||
| ] |
There was a problem hiding this comment.
The MCP server URL includes what appears to be embedded credentials/token material. Committing this leaks access to the Gumloop Airtable MCP endpoint; move the secret to an environment variable/secret manager and commit only a redacted placeholder (or remove this file from the repo).
| "sendBody": true, | ||
| "specifyBody": "json", | ||
| "jsonBody": "={\n \"prompt\": $json['Image Prompt'],\n \"image_size\": \"square_hd\",\n \"num_inference_steps\": 28,\n \"guidance_scale\": 3.5,\n \"num_images\": 1,\n \"enable_safety_checker\": false,\n \"seed\": Math.floor(Math.random() * 2147483647)\n}", | ||
| "options": {} |
There was a problem hiding this comment.
The jsonBody expression is not valid n8n expression syntax as written: $json['Image Prompt'] and Math.floor(...) are not wrapped in {{ }}/stringified, so this will be sent literally or fail evaluation. Use proper n8n expressions (e.g., {{ $json['Image Prompt'] }}) and ensure the body is valid JSON after interpolation.
| if command -v jq &> /dev/null; then | ||
| HAS_JQ=true | ||
| else | ||
| HAS_JQ=false | ||
| echo -e "${YELLOW}Note: jq not installed. Workflows will be saved without pretty-printing.${NC}" | ||
| echo "Install jq for better formatting: sudo apt-get install jq" | ||
| echo "" | ||
| fi | ||
|
|
||
| echo "================================================" | ||
| echo "Cyclone-S5 Workflow Backup" | ||
| echo "================================================" | ||
| echo "Source: ${N8N_URL}" | ||
| echo "Target: ${WORKFLOWS_DIR}" | ||
| echo "Backup: ${BACKUP_DIR}" | ||
| echo "" | ||
|
|
||
| # Fetch all workflows from n8n | ||
| echo -e "${YELLOW}Fetching workflows from n8n...${NC}" | ||
| workflows=$(curl -s \ | ||
| -H "X-N8N-API-KEY: ${N8N_API_KEY}" \ | ||
| "${N8N_URL}/api/v1/workflows") | ||
|
|
||
| # Check if request was successful | ||
| if [ $? -ne 0 ]; then | ||
| echo -e "${RED}ERROR: Failed to fetch workflows from n8n${NC}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Check if workflows data is valid JSON | ||
| if ! echo "$workflows" | jq . > /dev/null 2>&1; then | ||
| echo -e "${RED}ERROR: Invalid response from n8n API${NC}" | ||
| echo "Response: $workflows" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
This script treats jq as optional (HAS_JQ=false when missing), but later still calls jq unconditionally to validate and parse the API response. On systems without jq, the script will fail even though it claims it can run without pretty-printing. Either make jq a hard requirement (exit if missing) or gate all jq usage behind the availability check and provide a non-jq fallback.
| "permissions": { | ||
| "allow": [ | ||
| "Bash(git mv:*)", | ||
| "Bash(git add:*)", | ||
| "Bash(git rm:*)" | ||
| ] |
There was a problem hiding this comment.
This appears to be a machine-local configuration file (settings.local.json) but it’s being committed. Consider adding it to .gitignore and providing a checked-in non-local template (or rename to a repo-scoped settings file) to avoid accidental local config drift and leaking developer-specific permissions.
| "permissions": { | |
| "allow": [ | |
| "Bash(git mv:*)", | |
| "Bash(git add:*)", | |
| "Bash(git rm:*)" | |
| ] | |
| "_comment": "Template for Claude permissions. Per-developer local permissions should be defined in an untracked settings.local.json file.", | |
| "permissions": { | |
| "allow": [] |
| Backups are saved to: | ||
| - `workflows/` - Latest version | ||
| - `workflows/backups/` - Timestamped copies | ||
|
|
||
| ### Validate Configuration |
There was a problem hiding this comment.
README claims timestamped workflow backups in workflows/backups/ are committed/pushed, but .gitignore ignores workflows/backups/* (except .gitkeep). Align documentation and ignore rules (either document that backups are kept out of git, or stop ignoring them if they’re meant to be versioned).
| 3. **Storage:** For batch status tracking, consider using n8n's database or Airtable itself | ||
| 4. **Webhook URLs:** Make sure webhook paths match exactly what's in `src/lib/n8n.ts` | ||
| 5. **Testing:** Test each workflow individually before connecting them |
There was a problem hiding this comment.
This references src/lib/n8n.ts, but there doesn’t appear to be any src/lib/n8n.ts in the repository. Update the doc to point to the correct location (or remove the reference) to avoid sending readers on a dead end.
| "parameters": { | ||
| "method": "POST", | ||
| "url": "={{ $env.N8N_WEBHOOK_URL }}/webhook/palmaura-generate-images", | ||
| "options": {} | ||
| }, | ||
| "id": "webhook-trigger", | ||
| "name": "Webhook Trigger", | ||
| "type": "n8n-nodes-base.webhook", | ||
| "typeVersion": 2, | ||
| "position": [0, 200], | ||
| "webhookId": "palmaura-generate-images", | ||
| "notes": "Alternative trigger via Airtable automation or manual call" | ||
| }, |
There was a problem hiding this comment.
This Webhook node is configured with method + url, which matches an HTTP Request node, not an n8n Webhook trigger (which typically uses a path and response settings). Additionally it references $env.N8N_WEBHOOK_URL, but the repo’s env template defines WEBHOOK_URL (no N8N_WEBHOOK_URL). As-is, this workflow may not import/run correctly; adjust to the Webhook node’s expected parameters and use the correct env var name (or remove the URL entirely for the trigger).
| "Create Image Record": { | ||
| "main": [ | ||
| [] | ||
| ] | ||
| }, |
There was a problem hiding this comment.
Create Image Record has no outgoing connection, while Update Ad Copy Record triggers Continue Batch. This means the next batch can start before the image record is created (and if the update fails, the batch may never continue). Consider wiring Create Image Record into the same continuation path (or merge/wait for both updates before Continue Batch).
| * Type definitions for the Ad Copy table and related workflows | ||
| */ | ||
|
|
||
| import { AirtableRecord, AirtableAttachment } from './AirtableBase'; |
There was a problem hiding this comment.
Unused import AirtableAttachment.
There was a problem hiding this comment.
13 issues found across 81 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="utils/n8n-helpers/airtable-ops.js">
<violation number="1" location="utils/n8n-helpers/airtable-ops.js:156">
P2: Airtable’s API expects `sort` parameters as indexed query keys (sort[0][field], sort[0][direction]); JSON-stringifying the sort array into a single `sort` param is not the documented format and may be ignored, leading to unsorted results.</violation>
</file>
<file name="utils/n8n-helpers/image-generation.js">
<violation number="1" location="utils/n8n-helpers/image-generation.js:46">
P2: Falsy check for seed overwrites valid seed values like 0, preventing deterministic output when callers intentionally pass 0.</violation>
</file>
<file name="scripts/validate-config.js">
<violation number="1" location="scripts/validate-config.js:119">
P2: `.env.example` validation only does a substring search, so a required key can be “found” in comments or as part of another variable name and still pass. This can let missing env variables slip through validation.</violation>
</file>
<file name="scripts/backup-workflows.sh">
<violation number="1" location="scripts/backup-workflows.sh:72">
P2: The n8n workflows list endpoint is paginated (default 100 items with nextCursor). This script only requests the first page, so backups will be incomplete for instances with more than one page of workflows.</violation>
<violation number="2" location="scripts/backup-workflows.sh:81">
P2: jq is treated as optional but used unconditionally for JSON validation/parsing, so the script will fail when jq is not installed.</violation>
<violation number="3" location="scripts/backup-workflows.sh:88">
P2: Valid JSON error responses lacking `.data` are treated as “no workflows” and exit 0, masking API failures. The script should validate that `.data` exists and is an array before proceeding.</violation>
</file>
<file name="workflows/gumloop-airtable-mcp.json">
<violation number="1" location="workflows/gumloop-airtable-mcp.json:7">
P1: Hardcoded token/credential-like values are embedded in the Airtable MCP URL. Secrets should not be committed to the repo; move them to environment variables or secret storage and build the URL at runtime.</violation>
</file>
<file name="workflows/README.md">
<violation number="1" location="workflows/README.md:178">
P2: In the Code node example, template IDs are written as `{{ $env... }}` strings. Expressions are only evaluated in node parameter fields, not inside Code node JavaScript, so these remain literal and Bannerbear will receive invalid template IDs. Use `$env.BANNERBEAR_TEMPLATE_*` (or `process.env`) directly in the Code node.</violation>
<violation number="2" location="workflows/README.md:380">
P2: The batch workflow never converts the `recordIds` array into individual items before Split In Batches, so `$json.recordId` will be undefined when calling `pipeline-start`. Add a Split Out/Function node to turn `recordIds` into per-item records before looping.</violation>
</file>
<file name=".github/workflows/backup-n8n.yml">
<violation number="1" location=".github/workflows/backup-n8n.yml:45">
P2: The n8n workflows list endpoint is paginated (default 100 results with `nextCursor`). This workflow only fetches the first page, so instances with >100 workflows will have incomplete backups.</violation>
</file>
<file name="clerk-nextjs-app/src/proxy.ts">
<violation number="1" location="clerk-nextjs-app/src/proxy.ts:1">
P2: Next.js will not execute this middleware because it is defined in `src/proxy.ts` instead of `src/middleware.ts` (or re-exported from one). Without a middleware entrypoint, Clerk middleware won’t run at all.</violation>
</file>
<file name="workflows/palmaura-fal-image-generation.json">
<violation number="1" location="workflows/palmaura-fal-image-generation.json:24">
P2: Webhook trigger parameters use HTTP Request fields (`method`/`url`) instead of Webhook node fields (`path`/`httpMethod`), so this webhook may not register or receive calls.</violation>
<violation number="2" location="workflows/palmaura-fal-image-generation.json:233">
P2: `Image Generated` is set to true for every successful prompt, but the search filter only selects records where `Image Generated != TRUE()`. For multi-prompt records, a single successful prompt marks the record as generated and prevents retries for failed prompts, leaving some prompts without images.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| "command": "npx", | ||
| "args": [ | ||
| "mcp-remote@0.1.12", | ||
| "https://mcp.gumloop.com/airtable/Po4tsiByVANmPe33wJygwM6qNJG3:d965ea51425a4c7e9c15f5d3b21088c3:eyJleHRlcm5hbF9jbGllbnQiOnRydWV9/mcp" |
There was a problem hiding this comment.
P1: Hardcoded token/credential-like values are embedded in the Airtable MCP URL. Secrets should not be committed to the repo; move them to environment variables or secret storage and build the URL at runtime.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At workflows/gumloop-airtable-mcp.json, line 7:
<comment>Hardcoded token/credential-like values are embedded in the Airtable MCP URL. Secrets should not be committed to the repo; move them to environment variables or secret storage and build the URL at runtime.</comment>
<file context>
@@ -0,0 +1,11 @@
+ "command": "npx",
+ "args": [
+ "mcp-remote@0.1.12",
+ "https://mcp.gumloop.com/airtable/Po4tsiByVANmPe33wJygwM6qNJG3:d965ea51425a4c7e9c15f5d3b21088c3:eyJleHRlcm5hbF9jbGllbnQiOnRydWV9/mcp"
+ ]
+ }
</file context>
| queryParams.view = options.view; | ||
| } | ||
| if (options.sort) { | ||
| queryParams.sort = JSON.stringify(options.sort); |
There was a problem hiding this comment.
P2: Airtable’s API expects sort parameters as indexed query keys (sort[0][field], sort[0][direction]); JSON-stringifying the sort array into a single sort param is not the documented format and may be ignored, leading to unsorted results.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At utils/n8n-helpers/airtable-ops.js, line 156:
<comment>Airtable’s API expects `sort` parameters as indexed query keys (sort[0][field], sort[0][direction]); JSON-stringifying the sort array into a single `sort` param is not the documented format and may be ignored, leading to unsorted results.</comment>
<file context>
@@ -0,0 +1,267 @@
+ queryParams.view = options.view;
+ }
+ if (options.sort) {
+ queryParams.sort = JSON.stringify(options.sort);
+ }
+ if (options.fields && Array.isArray(options.fields)) {
</file context>
| const enhancedPrompt = `${cleanPrompt}, clean composition, no text, no watermark, no logo, professional photography`; | ||
|
|
||
| // Generate random seed if not provided | ||
| if (!params.seed) { |
There was a problem hiding this comment.
P2: Falsy check for seed overwrites valid seed values like 0, preventing deterministic output when callers intentionally pass 0.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At utils/n8n-helpers/image-generation.js, line 46:
<comment>Falsy check for seed overwrites valid seed values like 0, preventing deterministic output when callers intentionally pass 0.</comment>
<file context>
@@ -0,0 +1,243 @@
+ const enhancedPrompt = `${cleanPrompt}, clean composition, no text, no watermark, no logo, professional photography`;
+
+ // Generate random seed if not provided
+ if (!params.seed) {
+ params.seed = Math.floor(Math.random() * 2147483647);
+ }
</file context>
|
|
||
| const missingKeys = []; | ||
| requiredKeys.forEach(key => { | ||
| if (!content.includes(key)) { |
There was a problem hiding this comment.
P2: .env.example validation only does a substring search, so a required key can be “found” in comments or as part of another variable name and still pass. This can let missing env variables slip through validation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/validate-config.js, line 119:
<comment>`.env.example` validation only does a substring search, so a required key can be “found” in comments or as part of another variable name and still pass. This can let missing env variables slip through validation.</comment>
<file context>
@@ -0,0 +1,370 @@
+
+ const missingKeys = [];
+ requiredKeys.forEach(key => {
+ if (!content.includes(key)) {
+ missingKeys.push(key);
+ }
</file context>
| fi | ||
|
|
||
| # Count workflows | ||
| workflow_count=$(echo "$workflows" | jq '.data | length' 2>/dev/null || echo "0") |
There was a problem hiding this comment.
P2: Valid JSON error responses lacking .data are treated as “no workflows” and exit 0, masking API failures. The script should validate that .data exists and is an array before proceeding.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/backup-workflows.sh, line 88:
<comment>Valid JSON error responses lacking `.data` are treated as “no workflows” and exit 0, masking API failures. The script should validate that `.data` exists and is an array before proceeding.</comment>
<file context>
@@ -0,0 +1,175 @@
+fi
+
+# Count workflows
+workflow_count=$(echo "$workflows" | jq '.data | length' 2>/dev/null || echo "0")
+
+if [ "$workflow_count" -eq 0 ]; then
</file context>
|
|
||
| // Get template ID based on format (these should match your Bannerbear templates) | ||
| const templateIds = { | ||
| square: '{{ $env.BANNERBEAR_TEMPLATE_SQUARE }}', |
There was a problem hiding this comment.
P2: In the Code node example, template IDs are written as {{ $env... }} strings. Expressions are only evaluated in node parameter fields, not inside Code node JavaScript, so these remain literal and Bannerbear will receive invalid template IDs. Use $env.BANNERBEAR_TEMPLATE_* (or process.env) directly in the Code node.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At workflows/README.md, line 178:
<comment>In the Code node example, template IDs are written as `{{ $env... }}` strings. Expressions are only evaluated in node parameter fields, not inside Code node JavaScript, so these remain literal and Bannerbear will receive invalid template IDs. Use `$env.BANNERBEAR_TEMPLATE_*` (or `process.env`) directly in the Code node.</comment>
<file context>
@@ -0,0 +1,566 @@
+
+// Get template ID based on format (these should match your Bannerbear templates)
+const templateIds = {
+ square: '{{ $env.BANNERBEAR_TEMPLATE_SQUARE }}',
+ story: '{{ $env.BANNERBEAR_TEMPLATE_STORY }}',
+ landscape: '{{ $env.BANNERBEAR_TEMPLATE_LANDSCAPE }}'
</file context>
| # Fetch all workflows | ||
| response=$(curl -s \ | ||
| -H "X-N8N-API-KEY: $N8N_API_KEY" \ | ||
| "$N8N_URL/api/v1/workflows") |
There was a problem hiding this comment.
P2: The n8n workflows list endpoint is paginated (default 100 results with nextCursor). This workflow only fetches the first page, so instances with >100 workflows will have incomplete backups.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/backup-n8n.yml, line 45:
<comment>The n8n workflows list endpoint is paginated (default 100 results with `nextCursor`). This workflow only fetches the first page, so instances with >100 workflows will have incomplete backups.</comment>
<file context>
@@ -0,0 +1,113 @@
+ # Fetch all workflows
+ response=$(curl -s \
+ -H "X-N8N-API-KEY: $N8N_API_KEY" \
+ "$N8N_URL/api/v1/workflows")
+
+ # Check if request was successful
</file context>
| @@ -0,0 +1,12 @@ | |||
| import { clerkMiddleware } from '@clerk/nextjs/server' | |||
There was a problem hiding this comment.
P2: Next.js will not execute this middleware because it is defined in src/proxy.ts instead of src/middleware.ts (or re-exported from one). Without a middleware entrypoint, Clerk middleware won’t run at all.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At clerk-nextjs-app/src/proxy.ts, line 1:
<comment>Next.js will not execute this middleware because it is defined in `src/proxy.ts` instead of `src/middleware.ts` (or re-exported from one). Without a middleware entrypoint, Clerk middleware won’t run at all.</comment>
<file context>
@@ -0,0 +1,12 @@
+import { clerkMiddleware } from '@clerk/nextjs/server'
+
+export default clerkMiddleware()
</file context>
| "columns": { | ||
| "mappingMode": "defineBelow", | ||
| "value": { | ||
| "Image Generated": true, |
There was a problem hiding this comment.
P2: Image Generated is set to true for every successful prompt, but the search filter only selects records where Image Generated != TRUE(). For multi-prompt records, a single successful prompt marks the record as generated and prevents retries for failed prompts, leaving some prompts without images.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At workflows/palmaura-fal-image-generation.json, line 233:
<comment>`Image Generated` is set to true for every successful prompt, but the search filter only selects records where `Image Generated != TRUE()`. For multi-prompt records, a single successful prompt marks the record as generated and prevents retries for failed prompts, leaving some prompts without images.</comment>
<file context>
@@ -0,0 +1,852 @@
+ "columns": {
+ "mappingMode": "defineBelow",
+ "value": {
+ "Image Generated": true,
+ "Image Gen Timestamp": "={{ $json.generatedAt }}",
+ "Image Seed": "={{ $json.seed }}"
</file context>
| }, | ||
| { | ||
| "parameters": { | ||
| "method": "POST", |
There was a problem hiding this comment.
P2: Webhook trigger parameters use HTTP Request fields (method/url) instead of Webhook node fields (path/httpMethod), so this webhook may not register or receive calls.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At workflows/palmaura-fal-image-generation.json, line 24:
<comment>Webhook trigger parameters use HTTP Request fields (`method`/`url`) instead of Webhook node fields (`path`/`httpMethod`), so this webhook may not register or receive calls.</comment>
<file context>
@@ -0,0 +1,852 @@
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "={{ $env.N8N_WEBHOOK_URL }}/webhook/palmaura-generate-images",
+ "options": {}
</file context>
Summary by cubic
Renamed the repo to Cyclone-S5 and rebuilt it around production-ready n8n workflows for AI ad creative generation. Adds centralized config, helper scripts, typed schemas, and automated daily backups for safer, easier operations.
New Features
Migration
Written for commit 7a9a1bb. Summary will update on new commits.