Skip to content
Open
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
2 changes: 1 addition & 1 deletion MIGRATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ Each migration skill reads the source platform's configuration, maps it to Creat
| Skill | Description | Install |
|-------|-------------|---------|
| **vercel-to-createos** | Migrate Next.js, Vite, React, Vue, Svelte apps from Vercel to CreateOS | `npx skills add https://github.com/NodeOps-app/skills --skill vercel-to-createos` |
| **netlify-to-createos** | Migrate web applications from Netlify to CreateOS — parses netlify.toml, maps build settings, env vars, redirects, and headers | `npx skills add https://github.com/NodeOps-app/skills --skill netlify-to-createos` |

## Coming soon

These skills are reserved namespaces with stub `SKILL.md` files in place. Until they ship, they route users to the concierge migration path at `mailto:business@nodeops.xyz`.

| Skill | Source platform | Config file(s) it will parse |
|-------|----------------|------------------------------|
| **netlify-to-createos** | Netlify | `netlify.toml` |
| **railway-to-createos** | Railway | `railway.json` or `railway.toml` |
| **heroku-to-createos** | Heroku | `Procfile`, `app.json` |
| **render-to-createos** | Render | `render.yaml` |
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ AI agent skills for the [NodeOps](https://nodeops.network) ecosystem. Works with
|-------|-------------|---------|
| **createos** | Deploy anything to production on CreateOS cloud platform | `npx skills add https://github.com/NodeOps-app/skills --skill createos` |
| **vercel-to-createos** | Migrate Next.js, Vite, React, Vue, Svelte apps from Vercel to CreateOS | `npx skills add https://github.com/NodeOps-app/skills --skill vercel-to-createos` |
| **netlify-to-createos** | Migrate web applications from Netlify to CreateOS — parses netlify.toml, maps build settings, env vars, redirects, and headers | `npx skills add https://github.com/NodeOps-app/skills --skill netlify-to-createos` |
| **claude-code-to-codex** | Migrate Claude Code CLI hooks, MCP servers, plugins, instructions, and sessions to Codex CLI | `npx skills add https://github.com/NodeOps-app/skills --skill claude-code-to-codex` |

### Migration skills

`vercel-to-createos` is the first shipped skill in the migration family. Stubs for `netlify-to-createos`, `railway-to-createos`, `heroku-to-createos`, `render-to-createos`, and `flyio-to-createos` are reserved and route users to the concierge migration path until they ship. See [MIGRATIONS.md](./MIGRATIONS.md) for the full list and roadmap.
`vercel-to-createos` and `netlify-to-createos` are shipped migration skills. Stubs for `railway-to-createos`, `heroku-to-createos`, `render-to-createos`, and `flyio-to-createos` are reserved and route users to the concierge migration path until they ship. See [MIGRATIONS.md](./MIGRATIONS.md) for the full list and roadmap.

### Agent migration skills

Expand Down
329 changes: 311 additions & 18 deletions skills/netlify-to-createos/SKILL.md

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions skills/netlify-to-createos/config/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"name": "netlify-to-createos",
"version": "1.0.0",
"description": "Migration skill: Netlify to CreateOS",

"source": {
"platform": "netlify",
"configFiles": ["netlify.toml"],
"secondaryConfigFiles": ["package.json"]
},

"frameworkDetection": {
"nextjs": { "detect": ["next.config.js", "next.config.mjs"], "createosSlug": "nextjs", "runtimes": ["node:18", "node:20", "node:22"] },
"react": { "detect": ["vite.config.ts", "craco.config.js"], "createosSlug": "reactjs-spa", "runtimes": ["node:18", "node:20", "node:22"] },
"vue": { "detect": ["vue.config.js", "nuxt.config.js"], "createosSlug": "vuejs-spa", "runtimes": ["node:18", "node:20"] },
"astro": { "detect": ["astro.config.mjs"], "createosSlug": "astro", "runtimes": ["node:18", "node:20", "node:22"] },
"eleventy": { "detect": [".eleventy.js"], "createosSlug": "static", "runtimes": ["static"] },
"hugo": { "detect": ["hugo.toml", "config.toml"], "createosSlug": "static", "runtimes": ["static"] },
"gatsby": { "detect": ["gatsby-config.js", "gatsby-config.ts"], "createosSlug": "reactjs-ssr", "runtimes": ["node:18", "node:20"] },
"svelte": { "detect": ["svelte.config.js"], "createosSlug": "static", "runtimes": ["node:18", "node:20"] },
"angular": { "detect": ["angular.json"], "createosSlug": "static", "runtimes": ["node:18", "node:20"] }
},

"featureSupport": {
"buildSettings": { "status": "automated", "notes": "netlify.toml [build] → CreateProject.settings" },
"envVars": { "status": "automated", "notes": "Mapped via UpdateProjectEnvironmentEnvironmentVariables" },
"redirects": { "status": "manual", "notes": "Implement via app-level routing" },
"headers": { "status": "manual", "notes": "Implement via app-level config" },
"functions": { "status": "manual", "notes": "Rewrite as REST endpoints + separate project" },
"edgeFunctions": { "status": "unsupported", "notes": "No CreateOS equivalent" },
"backgroundFunctions": { "status": "unsupported", "notes": "Use queue workers / cron jobs" },
"plugins": { "status": "manual", "notes": "Per-plugin assessment required" },
"forms": { "status": "unsupported", "notes": "Recommend Formspree, Web3Forms, custom" },
"identity": { "status": "unsupported", "notes": "Recommend Auth0, Clerk, Supabase" },
"splitTesting": { "status": "unsupported", "notes": "Use app-level A/B testing" },
"deployPreviews": { "status": "automated", "notes": "Branch-based environments" },
"branchDeploy": { "status": "automated", "notes": "CreateProjectEnvironment per branch" }
},

"envVarMapping": {
"NETLIFY": { "action": "remove", "reason": "Netlify-specific, not needed on CreateOS" },
"CONTEXT": { "action": "remove", "reason": "Netlify-specific, hardcode if needed" },
"URL": { "action": "replace", "target": "CREATEOS_DEPLOYMENT_URL", "reason": "Deployment URL" },
"DEPLOY_URL": { "action": "replace", "target": "CREATEOS_DEPLOYMENT_URL", "reason": "Deployment URL" },
"DEPLOY_PRIME_URL": { "action": "replace", "target": "CREATEOS_DEPLOYMENT_URL", "reason": "Deployment URL" },
"DEPLOY_PREVIEW_URL": { "action": "replace", "target": "CREATEOS_DEPLOYMENT_URL", "reason": "Preview URL" },
"NETLIFY_DEV": { "action": "remove", "reason": "Local dev only" },
"NETLIFY_URL": { "action": "remove", "reason": "Netlify-specific" },
"NETLIFY_LFS": { "action": "remove", "reason": "Netlify-specific" },
"NETLIFY_LOCAL": { "action": "remove", "reason": "Local dev only" }
},

"codePatterns": [
{ "pattern": "process\\.env\\.NETLIFY", "severity": "warn", "action": "flag", "message": "Netlify-specific env var" },
{ "pattern": "exports\\.handler", "severity": "warn", "action": "flag", "message": "Netlify Functions handler pattern" },
{ "pattern": "@netlify/functions", "severity": "warn", "action": "flag", "message": "Netlify Functions SDK" },
{ "pattern": "@netlify/", "severity": "info", "action": "flag", "message": "Netlify package" },
{ "pattern": "netlify-", "severity": "info", "action": "flag", "message": "Netlify-specific code" }
],

"supportedRuntimes": ["node:18", "node:20", "node:22", "python:3.11", "python:3.12", "golang:1.22", "golang:1.25", "rust:1.75", "bun:1.1", "bun:1.3", "static"],

"resourceDefaults": {
"cpu": 200,
"memory": 500,
"replicas": 1,
"cpuMax": 500,
"memoryMax": 1024,
"replicasMax": 3
},

"namingConstraints": {
"uniqueName": { "pattern": "^[a-zA-Z0-9-]+$", "minLength": 4, "maxLength": 32 },
"displayName": { "pattern": "^[a-zA-Z0-9 _-]+$", "minLength": 4, "maxLength": 48 },
"description": { "minLength": 4, "maxLength": 2048 }
}
}
205 changes: 205 additions & 0 deletions skills/netlify-to-createos/references/migration-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Netlify Migration Patterns

Common code patterns encountered during Netlify → CreateOS migration,
with recommended actions for the AI agent.

---

## 1. Netlify Functions → REST Endpoints

### Netlify Pattern (exports.handler)

```javascript
// netlify/functions/hello.js
exports.handler = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({ message: "Hello!" }),
headers: { "Content-Type": "application/json" }
}
}
```

### CreateOS Equivalent (Express)

```javascript
// api/hello.js (or Express route)
import express from 'express'
const app = express()

app.get('/api/hello', (req, res) => {
res.json({ message: "Hello!" })
})
```

### Key differences to flag:
- `event.queryStringParameters` → `req.query`
- `event.pathParameters` → `req.params`
- `event.body` → `req.body` (with body parser)
- `context.clientContext` → Use auth middleware
- Multiple functions → Single Express app with multiple routes

---

## 2. Netlify Environment Variables

### Environment variable access patterns

```javascript
// Netlify
const apiUrl = process.env.URL // Netlify-specific

// CreateOS
const apiUrl = process.env.CREATEOS_DEPLOYMENT_URL // CreateOS equivalent
```

### Flag list:
| Netlify Expression | Action |
|--------------------|--------|
| `process.env.URL` | Replace with `process.env.CREATEOS_DEPLOYMENT_URL` |
| `process.env.DEPLOY_URL` | Replace with `process.env.CREATEOS_DEPLOYMENT_URL` |
| `process.env.DEPLOY_PRIME_URL` | Replace with `process.env.CREATEOS_DEPLOYMENT_URL` |
| `process.env.CONTEXT` | Remove or hardcode |
| `process.env.NETLIFY` | Remove |
| `process.env.NETLIFY_DEV` | Remove |
| `process.env.NETLIFY_LOCAL` | Remove |

---

## 3. Netlify Redirects → App-Level Routing

### Next.js (next.config.js)

```javascript
// Instead of netlify.toml redirects:
// [[redirects]]
// from = "/blog/*"
// to = "/news/:splat"
// status = 301

module.exports = {
async redirects() {
return [
{
source: '/blog/:path*',
destination: '/news/:path*',
permanent: true,
},
]
}
}
```

### Express (app.js)

```javascript
// Instead of netlify.toml redirects:
app.get('/old-path', (req, res) => {
res.redirect(301, '/new-path')
})

// Proxy pattern:
app.use('/api/*', async (req, res) => {
const response = await fetch(`https://api.example.com${req.originalUrl}`)
const data = await response.json()
res.json(data)
})
```

---

## 4. Netlify Functions with middleware

### Netlify middleware pattern

```javascript
// netlify/functions/with-auth.js
const withAuth = (handler) => async (event, context) => {
// auth check
return handler(event, context)
}
```

### CreateOS equivalent

```javascript
// Express middleware
const withAuth = (req, res, next) => {
// auth check
next()
}

app.get('/api/protected', withAuth, (req, res) => {
res.json({ secret: "data" })
})
```

---

## 5. Large Assets / Media

Netlify Large Media → CreateOS guidance:
- Migrate assets to object storage (AWS S3, Cloudflare R2, etc.)
- Update asset URLs in the codebase
- Use CDN for asset delivery

---

## 6. Netlify Forms → External Service

```javascript
// Instead of Netlify Forms:
// <form netlify>
// <input name="email" />
// </form>

// Use Formspree or similar:
// <form action="https://formspree.io/f/your-id" method="POST">
// <input name="email" />
// </form>
```

---

## 7. Complete Function Migration Example

### Netlify (before)

```javascript
// netlify/functions/subscribe.js
const stripe = require('stripe')(process.env.STRIPE_KEY)

exports.handler = async (event) => {
const { email, plan } = JSON.parse(event.body)

const customer = await stripe.customers.create({ email })

return {
statusCode: 200,
body: JSON.stringify({ customerId: customer.id })
}
}
```

### CreateOS (after)

```javascript
// app.js
import express from 'express'
import Stripe from 'stripe'

const app = express()
app.use(express.json())

const stripe = new Stripe(process.env.STRIPE_KEY)

app.post('/api/subscribe', async (req, res) => {
const { email, plan } = req.body

const customer = await stripe.customers.create({ email })

res.json({ customerId: customer.id })
})

export default app
```
Loading