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
66 changes: 66 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Project Overview

**Code Sync** = Framer plugin + CLI to upload/export `.tsx` between local FS and Framer.

- **Plugin** (`src/`): React app inside Framer
- **CLI** (`cli/`): Push files via `framer-api`

## Commands

Plugin:
- `pnpm dev` dev server (https, mkcert)
- `pnpm build` prod build
- `pnpm lint`

CLI (global):
- `framer-code-sync-cli push` push changed
- `framer-code-sync-cli push --force` push all
- `framer-code-sync-cli push --yes` skip confirm

CLI dev (from `cli/`):
- `pnpm build` compile to dist/
- `pnpm link --global` link globally

## Architecture

### Plugin (`src/`)
- `App.tsx` tabs: Upload / Export / Docs
- `pages/upload` drag-drop upload + transforms
- `pages/export` export Framer code zip
- `pages/docs` docs

Upload flow (`pages/upload/lib`):
1. load config (`config-loader`)
2. read files + paths (`file-processing`)
3. string/import transforms (`string-transforms`)
4. upload: placeholder → real content (`upload-logic`)

Types (`types.ts`):
- `CodeSyncConfig`
- `ImportReplacementRule`, `StringReplacementRule`
- `UploadState`

### CLI (`cli/`)
- `index.ts` entry point, command router
- `push.ts` exports `runPush()`, args `--force`, `--yes`
- `lib/file-scanner` tsx scan from cwd + mtime filter
- `lib/transform` load config from cwd + apply rules
- `lib/framer-push` upload via API

Globally installable via `npm i -g framer-code-sync-cli`.
Needs `.env` in cwd with `FRAMER_PROJECT_URL`.

## Config

`framer-code-sync.config.json` at upload root:
- `version`
- `importReplacements`
- `stringReplacements`
- `ignoredFiles`

## Code Style

- Tailwind only, no CSS files
- Handlers: `handleClick`, `handleKeyDown`
- Early returns
- Use `framer-plugin` SDK
38 changes: 38 additions & 0 deletions .cursor/rules/framer-plugin.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
globs: src/*
alwaysApply: false
---
You are a Senior Front-End Developer and an Expert in ReactJS, TypeScript, HTML, CSS and TailwindCSS. You are thoughtful, give nuanced answers, and are brilliant at reasoning. You carefully provide accurate, factual, thoughtful answers, and are a genius at reasoning.

- Follow the user’s requirements carefully & to the letter.
- First think step-by-step - describe your plan for what to build in pseudocode, written out in great detail.
- Confirm, then write code!
- Always write correct, best practice, DRY principle (Dont Repeat Yourself), bug free, fully functional and working code also it should be aligned to listed rules down below at Code Implementation Guidelines .
- Focus on easy and readability code, over being performant.
- Fully implement all requested functionality.
- Leave NO todo’s, placeholders or missing pieces.
- Ensure code is complete! Verify thoroughly finalised.
- Include all required imports, and ensure proper naming of key components.
- Be concise Minimize any other prose.
- If you think there might not be a correct answer, you say so.
- If you do not know the answer, say so, instead of guessing.

### Coding Environment

The user asks questions about the following coding languages:

- ReactJS
- TypeScript
- TailwindCSS
- HTML
- CSS
- Framer Plugin

### Code Implementation Guidelines

Follow these rules when you write code:

- Use early returns whenever possible to make the code more readable.
- Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
- Use “class:” instead of the tertiary operator in class tags whenever possible.
- Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
69 changes: 69 additions & 0 deletions .cursor/rules/project-overview.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
alwaysApply: true
---
# Project Overview

**Code Sync** = Framer plugin + CLI to upload/export `.tsx` between local FS and Framer.

- **Plugin** (`src/`): React app inside Framer
- **CLI** (`cli/`): Push files via `framer-api`

## Commands

Plugin:
- `pnpm dev` dev server (https, mkcert)
- `pnpm build` prod build
- `pnpm lint`

CLI (global):
- `framer-code-sync-cli push` push changed
- `framer-code-sync-cli push --force` push all
- `framer-code-sync-cli push --yes` skip confirm

CLI dev (from `cli/`):
- `pnpm build` compile to dist/
- `pnpm link --global` link globally

## Architecture

### Plugin (`src/`)
- `App.tsx` tabs: Upload / Export / Docs
- `pages/upload` drag-drop upload + transforms
- `pages/export` export Framer code zip
- `pages/docs` docs

Upload flow (`pages/upload/lib`):
1. load config (`config-loader`)
2. read files + paths (`file-processing`)
3. string/import transforms (`string-transforms`)
4. upload: placeholder → real content (`upload-logic`)

Types (`types.ts`):
- `CodeSyncConfig`
- `ImportReplacementRule`, `StringReplacementRule`
- `UploadState`

### CLI (`cli/`)
- `index.ts` entry point, command router
- `push.ts` exports `runPush()`, args `--force`, `--yes`
- `lib/file-scanner` tsx scan from cwd + mtime filter
- `lib/transform` load config from cwd + apply rules
- `lib/framer-push` upload via API

Globally installable via `npm i -g framer-code-sync-cli`.
Needs `.env` in cwd with `FRAMER_PROJECT_URL`.

## Config

`framer-code-sync.config.json` at upload root:
- `version`
- `importReplacements`
- `stringReplacements`
- `ignoredFiles`

## Code Style

- Tailwind only, no CSS files
- Handlers: `handleClick`, `handleKeyDown`
- Early returns
- Use `framer-plugin` SDK
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ yarn-error.log\*

plugin.zip

.cursor
/comps
/comps
.env
.framer-push-time
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ This Framer plugin is built as a modern React application with the following tec
- **CSS Styling** - Combination of inline styles and external `App.css` file. Planning to migrate to Tailwind CSS in the future.
- **ESLint** - Code linting and quality assurance

## 🤖 AI Agentic Coding Support

This repository includes `.cursor` and `.claude` folders with rules and context specifically designed to enhance AI agentic coding experiences. These folders contain:

- **`.cursor/rules/`** - Cursor IDE rules for improved AI-assisted development
- **`.claude/`** - Claude Code AI context and instructions for better code understanding

These files provide AI agents with project-specific knowledge, coding standards, and development workflows to ensure consistent and high-quality contributions.

## ⚡ Quick Start

1. **Select your upload mode** — folder or individual files
Expand Down Expand Up @@ -126,6 +135,56 @@ Your selected environment is stored per project via `framer.setPluginData`, so c
- `Config not applied` — Ensure `framer-code-sync.config.json` is at the root of your uploaded folder
- `Import errors` — Verify that replacement URLs and paths are correct

## 💻 CLI

Push `.tsx` files to Framer from the command line — no plugin UI needed.

### Installation

**From source (current):**

```bash
git clone https://github.com/david-mcbacon/code-sync-framer-plugin.git
cd framer-code-sync/cli
pnpm install && pnpm build

# Link globally (first time may need: pnpm setup && restart terminal)
pnpm link --global
```

**From npm (once published):**

```bash
npm i -g framer-code-sync-cli
```

### Setup

Create `.env` in your project root:

```env
FRAMER_PROJECT_URL=https://framer.com/projects/YOUR-PROJECT-ID
FRAMER_API_KEY=YOUR-API-KEY
```

Optionally add `framer-code-sync.config.json` for transforms (same format as plugin config).

### Usage

```bash
framer-code-sync-cli push # push changed .tsx files
framer-code-sync-cli push --force # push all files
framer-code-sync-cli push --yes # skip confirmation
framer-code-sync-cli --help # show help
```

### How it works

1. Scans all `.tsx` files in current directory (recursive)
2. Filters to only changed files since last push (stored in `.framer-push-time`)
3. Applies transforms from config (if present)
4. Pushes to Framer via `framer-api`

## 🤝 Contributing

Every developer’s needs are different — that’s why this plugin is open source.
Expand Down
3 changes: 3 additions & 0 deletions cli-example-folder-push/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Get this from your Framer project settings
FRAMER_PROJECT_URL=https://framer.com/projects/Your-Project--xxxxxxxxxxxxxx
FRAMER_API_KEY=xxx
7 changes: 7 additions & 0 deletions cli-example-folder-push/Comp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'

export default function Comp() {
return (
<div>Comp</div>
)
}
7 changes: 7 additions & 0 deletions cli-example-folder-push/Comp2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'

export default function Comp2() {
return (
<div>Comp2</div>
)
}
5 changes: 5 additions & 0 deletions cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env
last-push.txt
.framer-push-time
node_modules/
/dist
54 changes: 54 additions & 0 deletions cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env node
import dotenv from "dotenv";
import path from "node:path";
import pc from "picocolors";

// Load .env from current working directory
dotenv.config({ path: path.join(process.cwd(), ".env") });

const args = process.argv.slice(2);
const command = args[0];

function printHelp() {
console.log(`
${pc.bold("framer-code-sync-cli")} - Push local .tsx files to Framer

${pc.bold("Usage:")}
framer-code-sync-cli <command> [options]

${pc.bold("Commands:")}
push Push changed .tsx files to Framer

${pc.bold("Push Options:")}
--force Push all files, ignore last push time
--yes Skip confirmation prompt

${pc.bold("Setup:")}
Create .env in your project root with:
FRAMER_PROJECT_URL=https://framer.com/projects/...

Optionally add framer-code-sync.config.json for transforms.
`);
}

async function main() {
if (!command || command === "-h" || command === "--help") {
printHelp();
process.exit(0);
}

if (command === "push" || command === "-p" || command === "--push") {
const { runPush } = await import("./push.js");
const pushArgs = command === "push" ? args.slice(1) : args.slice(1);
await runPush(pushArgs);
} else {
console.error(pc.red(`Unknown command: ${command}`));
printHelp();
process.exit(1);
}
}

main().catch((err) => {
console.error(pc.red("Fatal error:"), err);
process.exit(1);
});
Loading