├── .gitignore
├── .jshintrc
├── .tern-project
├── README.md
├── bin
├── framer-new.js
├── framer-preview.js
├── framer-update.js
└── framer.js
├── boilerplate
├── module
│ ├── .framer.json
│ ├── .gitignore
│ ├── .jshintrc
│ ├── .tern-project
│ ├── Makefile
│ ├── README.md
│ ├── index.js
│ ├── package.json
│ └── test.html
└── project
│ ├── .framer
│ └── framer.json
│ ├── .gitignore
│ ├── .jshintrc
│ ├── .tern-project
│ ├── Makefile
│ ├── README.md
│ ├── images
│ └── framer-icon.png
│ ├── index.html
│ ├── index.js
│ ├── modules
│ └── myModule
│ │ ├── background.png
│ │ ├── data.json
│ │ └── index.js
│ └── package.json
├── lib
└── framer_test.js
├── package.json
└── preview.png
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi": true,
3 | "node": true,
4 | "esnext": true,
5 | "forin": true,
6 | "latedef": "nofunc",
7 | "supernew": true,
8 | "unused": true
9 | }
10 |
--------------------------------------------------------------------------------
/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "complete_strings": {},
4 | "node": {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Framer CLI
2 |
3 | > Providing most of the functionality of Framer Studio, but from the comfort of
4 | > your terminal.
5 |
6 |
7 |
8 | Framer CLI is in its infancy, but the aim is to create a decent way to build
9 | quick prototypes/dynamic layouts in code from the editor of your choice. The
10 | current implementation of this tool requires [Node][1].
11 |
12 | ## Who is this for?
13 |
14 | This is not a replacement to [Framer Studio][2] and is best suited for those
15 | who are comfortable with Framer's API and using the command line.
16 |
17 | ## Features
18 |
19 | - CoffeeScript & ECMAScript 6 JS. It will handle CoffeeScript, es6-compliant
20 | JavaScript, or a mix of the two.
21 | - Local server for previewing/debugging.
22 | - Handles true [Node-style modules][3]. Place any code, assets, etc. that you
23 | want in the `modules` folder and `require` them in your main `index.js` file.
24 | Make use of Node modules and third-party Framer modules as well.
25 | - Live reloading when any of the files in your dependency tree change.
26 | - **WIP:** Intelligent completions that are scoped appropriately. This uses
27 | [Tern][4] and requires using an editor with a [Tern plugin][5].
28 | - Quickly generate project and module boilerplate.
29 |
30 | ## Usage
31 |
32 | ```bash
33 | $ npm install -g peteschaffner/framer-cli
34 | $ framer path/to/my/project &
35 | $ vim path/to/my/project/index.js
36 | ```
37 |
38 | The best way to learn is probably to poke around the project and module
39 | boilerplate that `framer(1)` generates. For more detailed instructions,
40 | `framer -h`.
41 |
42 | [1]: https://nodejs.org/
43 | [2]: http://framerjs.com/
44 | [3]: https://nodejs.org/api/modules.html#modules_folders_as_modules
45 | [4]: http://ternjs.net/
46 | [5]: http://ternjs.net/#plugins
47 |
--------------------------------------------------------------------------------
/bin/framer-new.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var colors = require('colors/safe');
8 | var exec = require('child_process').exec;
9 | var fs = require('fs-extra');
10 | var path = require('path');
11 | var program = require('commander');
12 |
13 | program
14 | .description('Create a project.')
15 | .arguments('[dir]')
16 | .option('-m, --module', 'create a module')
17 | .parse(process.argv);
18 |
19 | var directory = path.resolve(program.args[0] || '.');
20 | var projectType = require('../lib/framer_test.js')(directory);
21 |
22 | // create [dir] if it doesn't exist
23 | if (!projectType) fs.mkdirpSync(directory);
24 |
25 | // scaffold project/module if [dir] is empty
26 | if (!!!fs.readdirSync(directory).length) {
27 | var projectType = program.module ? 'module' : 'project';
28 | var toPath = '../boilerplate/' + projectType;
29 |
30 | console.log(colors.grey('Creating %s...'), projectType);
31 | fs.copySync(path.resolve(__dirname, toPath), directory);
32 |
33 | // move into [dir]
34 | process.chdir(directory);
35 |
36 | console.log(colors.grey('Installing project dependencies...'));
37 | exec('framer update');
38 | exec('npm install --production');
39 | } else console.warn(colors.red('Error: ') + directory + ' is not empty');
40 |
41 |
--------------------------------------------------------------------------------
/bin/framer-preview.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var auth = require('basic-auth');
8 | var babelify = require('babelify');
9 | var browserify = require('browserify');
10 | var chokidar = require('chokidar');
11 | var coffeeify = require('coffeeify');
12 | var colors = require('colors/safe');
13 | var connect = require('connect');
14 | var exec = require('child_process').exec;
15 | var fs = require('fs-extra');
16 | var livereload = require('connect-livereload');
17 | var livereloadServer = require('tiny-lr');
18 | var path = require('path');
19 | var program = require('commander');
20 | var serveIndex = require('serve-index');
21 | var serveStatic = require('serve-static');
22 | var watchify = require('watchify');
23 |
24 |
25 | program
26 | .description('Preview your project.')
27 | .arguments('[dir]')
28 | .option('-p, --port ', 'specify the port [3000]', Number, 3000)
29 | .parse(process.argv);
30 |
31 | var directory = path.resolve(program.args[0] || '.');
32 | var projectType = require('../lib/framer_test.js')(directory);
33 |
34 | if (!projectType) {
35 | console.warn(colors.red('Error: ') + 'not a "framer-cli" project');
36 | process.exit(1);
37 | }
38 |
39 | // move into [dir]
40 | process.chdir(directory);
41 |
42 | // setup the server
43 | var server = connect();
44 |
45 | // watch files
46 | chokidar
47 | .watch(directory, { ignored: /node_modules|[\/\\]\./ })
48 | .on('all', function(event, file) {
49 | livereloadServer.changed(file);
50 | });
51 |
52 | // inject livereload.js
53 | if (process.env.NODE_ENV !== 'production') {
54 | server.use(livereload({ port: program.port }));
55 | }
56 |
57 | // http basic auth
58 | if (process.env.NODE_ENV === 'production') {
59 | server.use(function(req, res, next) {
60 | var creds = auth(req);
61 | var name = process.env.NAME || '';
62 | var pass = process.env.PASS || '';
63 |
64 | if (!creds || creds.name !== name || creds.pass !== pass) {
65 | res.writeHead(401, {
66 | 'WWW-Authenticate': 'Basic realm="You have to pay the troll toll"'
67 | });
68 | res.end();
69 | } else {
70 | next();
71 | }
72 | });
73 | }
74 |
75 | // browserify
76 | var b = browserify({
77 | basedir: directory,
78 | cache: {},
79 | debug: true,
80 | extensions: ['.coffee'],
81 | packageCache: {},
82 | paths: [directory + '/modules']
83 | });
84 |
85 | b.transform(coffeeify, { global: true });
86 | b.transform(babelify, { global: true });
87 | b.add('index');
88 | if (projectType === 'module') b.require('./index', { expose: '.' });
89 | var w = watchify(b);
90 |
91 | // create build file for distribution
92 | if (process.env.NODE_ENV !== 'production') {
93 | w.on('bundle', function(bundle) {
94 | var bundleFile = fs.createWriteStream(directory + '/.bundle.js');
95 |
96 | bundle.pipe(bundleFile);
97 | });
98 | }
99 |
100 | // bundle on request
101 | server.use(function(req, res, next) {
102 | if (req.url !== '/.bundle.js') return next();
103 |
104 | w.bundle()
105 | .on('error', function(err) {
106 | console.error(colors.red('\nError: ') + err.message);
107 | res.end('console.error("' + err.message + '")');
108 | this.emit('end');
109 | })
110 | .pipe(res);
111 | });
112 |
113 | // static files
114 | server.use(serveStatic(directory));
115 | server.use(serveIndex(directory));
116 |
117 | // livereload server
118 | if (process.env.NODE_ENV !== 'production') {
119 | server.use(livereloadServer.middleware({ app: server }));
120 | }
121 |
122 | // start the server
123 | server.listen(process.env.PORT || program.port, function () {
124 | var htmlFile = (projectType === 'module') ? 'test.html' : '';
125 |
126 | console.log(
127 | colors.grey('%s running at ') + colors.cyan('http://localhost:%s/%s'),
128 | projectType.charAt(0).toUpperCase() + projectType.slice(1),
129 | program.port,
130 | htmlFile
131 | );
132 |
133 | exec('open "http://localhost:' + program.port + '/' + htmlFile + '"');
134 | });
135 |
136 |
137 |
--------------------------------------------------------------------------------
/bin/framer-update.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var colors = require('colors/safe');
8 | var fs = require('fs-extra');
9 | var path = require('path');
10 | var program = require('commander');
11 | var request = require('sync-request');
12 |
13 | program
14 | .description('Update Framer.js framework.')
15 | .arguments('[dir]')
16 | .parse(process.argv);
17 |
18 | var directory = path.resolve(program.args[0] || '.');
19 | var projectType = require('../lib/framer_test.js')(directory);
20 |
21 | if (!projectType) {
22 | console.warn(colors.red('Error: ') + 'not a "framer-cli" project');
23 | process.exit(1);
24 | } else if (projectType === 'module') process.exit(1);
25 |
26 | console.log(colors.grey('Updating Framer.js...'));
27 |
28 | ['framer.js', 'framer.js.map'].forEach(function(file) {
29 | var res = request('GET', 'http://builds.framerjs.com/latest/' + file);
30 |
31 | fs.writeFileSync(directory + '/.framer/' + file, res.getBody());
32 | });
33 |
--------------------------------------------------------------------------------
/bin/framer.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var program = require('commander');
8 |
9 | program
10 | .version(require('../package.json').version)
11 | .description('A Framer.js CLI for quickly building modular prototypes.')
12 | .command('new [dir]', 'create a project')
13 | .command('preview [dir]', 'preview a project')
14 | .command('update [dir]', 'update Framer.js framework')
15 | .parse(process.argv);
16 |
17 |
--------------------------------------------------------------------------------
/boilerplate/module/.framer.json:
--------------------------------------------------------------------------------
1 | {
2 | "!name": "framer",
3 | "print": {
4 | "!doc": "Printing allows you to inspect variables on runtime. It works similarly to console.log, only when using print, the output is shown directly within your prototype.",
5 | "!url": "http://framerjs.com/docs/#print",
6 | "!type": "fun(text: string) -> string"
7 | },
8 | "Framer": {
9 | "Defaults": {
10 | "!doc": "The Framer.Defaults allows you to override the default properties for Layers and Animations when they are created.",
11 | "!url": "http://framerjs.com/docs/#defaults.defaults",
12 | "Animation": {
13 | "curve": "string",
14 | "time": "number"
15 | },
16 | "Layer": {
17 | "backgroundColor": "string",
18 | "height": "number",
19 | "width": "number"
20 | }
21 | }
22 | },
23 | "Canvas": {
24 | "!doc": "The Canvas object contains the size for the current entire document in pixels. It will change if you resize your document by resizing the window it is in.",
25 | "!url": "http://framerjs.com/docs/#canvas.canvas",
26 | "width": {
27 | "!doc": "The width of the current entire document in pixels. This property is read-only.",
28 | "!url": "http://framerjs.com/docs/#canvas.width",
29 | "!type": "number"
30 | },
31 | "height": {
32 | "!doc": "The height of the current entire document in pixels. This property is read-only.",
33 | "!url": "http://framerjs.com/docs/#canvas.height",
34 | "!type": "number"
35 | },
36 | "size": {
37 | "!doc": "The width and height of the current entire document in pixels. This property is read-only.",
38 | "!url": "http://framerjs.com/docs/#canvas.size",
39 | "width": "Canvas.width",
40 | "height": "Canvas.height"
41 | }
42 | },
43 | "Screen": {
44 | "!doc": "The Screen object contains the size for the current device screen. The size will change when you update to a different device. If the device is full screen, it will be equal to the Canvas size.",
45 | "!url": "http://framerjs.com/docs/#screen.screen",
46 | "width": {
47 | "!doc": "The width of the current device screen in pixels. This property is read-only.",
48 | "!url": "http://framerjs.com/docs/#screen.width",
49 | "!type": "number"
50 | },
51 | "height": {
52 | "!doc": "The height of the current device screen in pixels. This property is read-only.",
53 | "!url": "http://framerjs.com/docs/#screen.height",
54 | "!type": "number"
55 | },
56 | "size": {
57 | "!doc": "The width and height of the current device screen in pixels. This property is read-only.",
58 | "!url": "http://framerjs.com/docs/#screen.size",
59 | "width": "Screen.width",
60 | "height": "Screen.height"
61 | }
62 | },
63 | "Layer": {
64 | "!doc": "Layers are the basic containers for Framer. They have positioning, size, visual properties and a hierarchy. They can contain images, videos, text or even arbitrary html.",
65 | "!url": "http://framerjs.com/docs/#layer.layer",
66 | "!type": "fn(options: object)",
67 | "prototype": {
68 | "id": {
69 | "!doc": "A unique identification number for this layer. No other layer will have this number. The layer id is read only and cannot be changed.",
70 | "!url": "http://framerjs.com/docs/index.html#layer.id",
71 | "!type": "number"
72 | },
73 | "name": {
74 | "!doc": "The layer name. This is not set by default but you can set it yourself. Imported layers from Sketch and Photoshop will have the source layer group set.",
75 | "!url": "http://framerjs.com/docs/index.html#layer.name",
76 | "!type": "string"
77 | },
78 | "x": {
79 | "!doc": "The x property of a layer defines its x position relative to the top left corner.",
80 | "!url": "http://framerjs.com/docs/index.html#layer.x",
81 | "!type": "number"
82 | },
83 | "y": "number",
84 | "z": "number",
85 | "width": "number",
86 | "height": "number"
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/boilerplate/module/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle.js
2 | node_modules
3 |
--------------------------------------------------------------------------------
/boilerplate/module/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi": true,
3 | "browser": true,
4 | "browserify": true,
5 | "esnext": true,
6 | "forin": true,
7 | "latedef": "nofunc",
8 | "supernew": true,
9 | "unused": true,
10 |
11 | "globals": {
12 | "Framer": true,
13 | "Layer": true,
14 | "Utils": true,
15 | "BackgroundLayer": true,
16 | "Canvas": true,
17 | "Screen": true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/boilerplate/module/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "libs": [
3 | "browser",
4 | "ecma6",
5 | "underscore",
6 | ".framer"
7 | ],
8 | "plugins": {
9 | "complete_strings": {}
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/boilerplate/module/Makefile:
--------------------------------------------------------------------------------
1 | start: node_modules
2 | npm start
3 |
4 | node_modules: package.json
5 | npm install
6 |
7 | clean:
8 | rm -rf .bundle.js node_modules
9 |
10 | .PHONY: clean
11 |
--------------------------------------------------------------------------------
/boilerplate/module/README.md:
--------------------------------------------------------------------------------
1 | # My Framer.js module
2 |
3 | A quick description of my module.
4 |
5 | ## API
6 |
7 | A quick description of the API.
8 |
9 | ## Development
10 |
11 | If you have `framer-cli` installed, `$ framer preview [path/to/this/module] &`
12 | or `$ cd path/to/this/module && make &`.
13 |
--------------------------------------------------------------------------------
/boilerplate/module/index.js:
--------------------------------------------------------------------------------
1 |
2 | var UILabel = require('framer-uilabel')
3 |
4 | module.exports = class RainbowLabel extends UILabel {
5 | constructor(opts={}) {
6 | super(opts);
7 |
8 | this.style.background = `linear-gradient(
9 | to right,
10 | red,
11 | orange,
12 | yellow,
13 | green,
14 | blue,
15 | indigo,
16 | violet
17 | )`;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/boilerplate/module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "framer-module",
3 | "version": "0.0.1",
4 | "description": "My Framer.js module.",
5 | "keywords": [
6 | "prototyping",
7 | "framerjs"
8 | ],
9 | "main": "index.js",
10 | "dependencies": {
11 | "framer-uilabel": "^0.1.0"
12 | },
13 | "devDependencies": {
14 | "framer-cli": "^0.1.0"
15 | },
16 | "scripts": {
17 | "start": "framer preview"
18 | },
19 | "framer": { "type": "module" }
20 | }
21 |
--------------------------------------------------------------------------------
/boilerplate/module/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/boilerplate/project/.framer/framer.json:
--------------------------------------------------------------------------------
1 | {
2 | "!name": "framer",
3 | "print": {
4 | "!doc": "Printing allows you to inspect variables on runtime. It works similarly to console.log, only when using print, the output is shown directly within your prototype.",
5 | "!url": "http://framerjs.com/docs/#print",
6 | "!type": "fun(text: string) -> string"
7 | },
8 | "Framer": {
9 | "Defaults": {
10 | "!doc": "The Framer.Defaults allows you to override the default properties for Layers and Animations when they are created.",
11 | "!url": "http://framerjs.com/docs/#defaults.defaults",
12 | "Animation": {
13 | "curve": "string",
14 | "time": "number"
15 | },
16 | "Layer": {
17 | "backgroundColor": "string",
18 | "height": "number",
19 | "width": "number"
20 | }
21 | }
22 | },
23 | "Canvas": {
24 | "!doc": "The Canvas object contains the size for the current entire document in pixels. It will change if you resize your document by resizing the window it is in.",
25 | "!url": "http://framerjs.com/docs/#canvas.canvas",
26 | "width": {
27 | "!doc": "The width of the current entire document in pixels. This property is read-only.",
28 | "!url": "http://framerjs.com/docs/#canvas.width",
29 | "!type": "number"
30 | },
31 | "height": {
32 | "!doc": "The height of the current entire document in pixels. This property is read-only.",
33 | "!url": "http://framerjs.com/docs/#canvas.height",
34 | "!type": "number"
35 | },
36 | "size": {
37 | "!doc": "The width and height of the current entire document in pixels. This property is read-only.",
38 | "!url": "http://framerjs.com/docs/#canvas.size",
39 | "width": "Canvas.width",
40 | "height": "Canvas.height"
41 | }
42 | },
43 | "Screen": {
44 | "!doc": "The Screen object contains the size for the current device screen. The size will change when you update to a different device. If the device is full screen, it will be equal to the Canvas size.",
45 | "!url": "http://framerjs.com/docs/#screen.screen",
46 | "width": {
47 | "!doc": "The width of the current device screen in pixels. This property is read-only.",
48 | "!url": "http://framerjs.com/docs/#screen.width",
49 | "!type": "number"
50 | },
51 | "height": {
52 | "!doc": "The height of the current device screen in pixels. This property is read-only.",
53 | "!url": "http://framerjs.com/docs/#screen.height",
54 | "!type": "number"
55 | },
56 | "size": {
57 | "!doc": "The width and height of the current device screen in pixels. This property is read-only.",
58 | "!url": "http://framerjs.com/docs/#screen.size",
59 | "width": "Screen.width",
60 | "height": "Screen.height"
61 | }
62 | },
63 | "Layer": {
64 | "!doc": "Layers are the basic containers for Framer. They have positioning, size, visual properties and a hierarchy. They can contain images, videos, text or even arbitrary html.",
65 | "!url": "http://framerjs.com/docs/#layer.layer",
66 | "!type": "fn(options: object)",
67 | "prototype": {
68 | "id": {
69 | "!doc": "A unique identification number for this layer. No other layer will have this number. The layer id is read only and cannot be changed.",
70 | "!url": "http://framerjs.com/docs/index.html#layer.id",
71 | "!type": "number"
72 | },
73 | "name": {
74 | "!doc": "The layer name. This is not set by default but you can set it yourself. Imported layers from Sketch and Photoshop will have the source layer group set.",
75 | "!url": "http://framerjs.com/docs/index.html#layer.name",
76 | "!type": "string"
77 | },
78 | "x": {
79 | "!doc": "The x property of a layer defines its x position relative to the top left corner.",
80 | "!url": "http://framerjs.com/docs/index.html#layer.x",
81 | "!type": "number"
82 | },
83 | "y": "number",
84 | "z": "number",
85 | "width": "number",
86 | "height": "number"
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/boilerplate/project/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle.js
2 | framer.js
3 | framer.js.map
4 | node_modules
5 |
--------------------------------------------------------------------------------
/boilerplate/project/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi": true,
3 | "browser": true,
4 | "browserify": true,
5 | "esnext": true,
6 | "forin": true,
7 | "latedef": "nofunc",
8 | "supernew": true,
9 | "unused": true,
10 |
11 | "globals": {
12 | "Framer": true,
13 | "Layer": true,
14 | "Utils": true,
15 | "BackgroundLayer": true,
16 | "Canvas": true,
17 | "Screen": true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/boilerplate/project/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "libs": [
3 | "browser",
4 | "ecma6",
5 | "underscore",
6 | "framer/framer"
7 | ],
8 | "plugins": {
9 | "complete_strings": {}
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/boilerplate/project/Makefile:
--------------------------------------------------------------------------------
1 | start: node_modules
2 | npm start
3 |
4 | node_modules: package.json
5 | npm install
6 |
7 | clean:
8 | rm -rf .framer/framer.{js,js.map} .bundle.js node_modules
9 |
10 | .PHONY: clean
11 |
--------------------------------------------------------------------------------
/boilerplate/project/README.md:
--------------------------------------------------------------------------------
1 | # My Framer.js project
2 |
3 | A quick description of my project.
4 |
5 | ## For developers
6 |
7 | The idea here is to create self-documenting designs/prototypes, and thus it will
8 | be beneficial to know where to look in the source.
9 |
10 | - `index.html`: open this in your browser to view and interact with the
11 | prototype
12 | - `index.js`: the main project file that holds design/interaction logic
13 | - `/images`: project-specific graphics and assets
14 | - `/modules`: project-specific components and design patterns that have been
15 | abstracted away either to keep `index.js` more readable or because they are
16 | not required for implementation
17 | - `/node_modules`: holds third-party components that may or may not be relevant
18 | for implementation
19 | - `package.json`: required for developing this prototype and lists third-party
20 | module dependencies
21 | - `Makefile`: used for development (assumes [Node][1] is installed)
22 |
23 | [1]: https://nodejs.org/
24 |
--------------------------------------------------------------------------------
/boilerplate/project/images/framer-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peteschaffner/framerjs-cli/9cb27f5112d438d5d5d65371eb90c63a4bd84b66/boilerplate/project/images/framer-icon.png
--------------------------------------------------------------------------------
/boilerplate/project/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/boilerplate/project/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Welcome to Framer
4 | *
5 | * Learn how to prototype:
6 | * - http://framerjs.com/learn
7 | * - https://github.com/peteschaffner/framer-cli
8 | */
9 |
10 | var Device = require('framer-device')
11 | var UIStatusBar = require('framer-uistatusbar')
12 | var myModule = require('myModule')
13 |
14 | new Device({ deviceType: 'iphone-6-silver' })
15 | new UIStatusBar({ style: 'light' })
16 |
17 | var background = new BackgroundLayer({
18 | image: myModule.image
19 | })
20 |
21 | Utils.labelLayer(background, myModule.data.title)
22 |
23 | var iconLayer = new Layer({
24 | width: 256/2,
25 | height: 256/2,
26 | image: 'images/framer-icon.png'
27 | })
28 | iconLayer.center()
29 |
30 | // Define a set of states with names (the original state is 'default')
31 | iconLayer.states.add({
32 | second: { y: 100, scale: 0.6, rotationZ: 100 },
33 | third: { y: 300, scale: 1.3, blur: 4 },
34 | fourth: { y: 200, scale: 0.9, blur: 2, rotationZ: 200 }
35 | })
36 |
37 | // Set the default animation options
38 | iconLayer.states.animationOptions = { curve: 'spring(500,12,0)' }
39 |
40 |
41 | // On a click, go to the next state
42 | iconLayer.on(Events.Click, () => iconLayer.states.next())
43 |
--------------------------------------------------------------------------------
/boilerplate/project/modules/myModule/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peteschaffner/framerjs-cli/9cb27f5112d438d5d5d65371eb90c63a4bd84b66/boilerplate/project/modules/myModule/background.png
--------------------------------------------------------------------------------
/boilerplate/project/modules/myModule/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "My Data"
3 | }
4 |
--------------------------------------------------------------------------------
/boilerplate/project/modules/myModule/index.js:
--------------------------------------------------------------------------------
1 |
2 | // Add the following line to your project in Framer Studio.
3 | // myModule = require 'myModule'
4 | // Reference the contents by name, like myModule.myFunction() or myModule.myVar
5 |
6 | exports.data = require('./data.json')
7 |
8 | exports.image = 'background.png'
9 |
10 | exports.myVar = 'myVariable'
11 |
12 | exports.myFunction = () => print('myFunction is running')
13 |
14 | exports.myArray = [1, 2, 3]
15 |
--------------------------------------------------------------------------------
/boilerplate/project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "framer-project",
3 | "version": "0.0.1",
4 | "description": "My Framer.js project.",
5 | "private": true,
6 | "main": "index.js",
7 | "dependencies": {
8 | "framer-device": "^0.1.0",
9 | "framer-uistatusbar": "^0.1.0"
10 | },
11 | "devDependencies": {
12 | "framer-cli": "^0.1.0"
13 | },
14 | "scripts": {
15 | "start": "framer preview"
16 | },
17 | "framer": { "type": "project" }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/framer_test.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Module dependencies.
4 | */
5 |
6 | module.exports = function (dir) {
7 | try {
8 | return require(dir + '/package.json').framer.type;
9 | }
10 | catch (err) {
11 | return false;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "framer-cli",
3 | "version": "0.2.3",
4 | "description": "A Framer.js CLI for quickly building modular prototypes.",
5 | "author": {
6 | "name": "Pete Schaffner",
7 | "email": "pjschaffner@gmail.com"
8 | },
9 | "homepage": "https://github.com/peteschaffner/framer-cli",
10 | "repository": {
11 | "type": "git",
12 | "url": "git+ssh://git@github.com/peteschaffner/framer-cli.git"
13 | },
14 | "keywords": [
15 | "prototyping",
16 | "framerjs"
17 | ],
18 | "license": "MIT",
19 | "bin": {
20 | "framer": "bin/framer.js"
21 | },
22 | "dependencies": {
23 | "babelify": "^6.0.2",
24 | "basic-auth": "^1.0.1",
25 | "browserify": "^10.2.0",
26 | "chokidar": "^1.0.1",
27 | "coffeeify": "^1.1.0",
28 | "colors": "^1.1.0",
29 | "commander": "^2.8.1",
30 | "connect": "^3.3.5",
31 | "connect-livereload": "^0.5.3",
32 | "fs-extra": "^0.18.3",
33 | "serve-index": "^1.6.4",
34 | "serve-static": "^1.9.3",
35 | "sync-request": "^2.0.1",
36 | "tiny-lr": "^0.1.5",
37 | "watchify": "^3.2.1"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/peteschaffner/framerjs-cli/9cb27f5112d438d5d5d65371eb90c63a4bd84b66/preview.png
--------------------------------------------------------------------------------