_ _ _____ _ _ ____ _____ _____ ____ _____ _____ ____
/ \ /\ / \ /__ __\ / \ / \__/| / _ \ /__ __\ / __/ / ___\ / __/ / __/ / _ \
| | || | | / \ | | | |\/|| | / \ | / \ | \ _____ | \ | \ | \ | | \|
| \_/| | |_/\ | | | | | | || | |-| | | | | /_ \____\ \___ | | /_ | /_ | |_/|
\____/ \____/ \_/ \_/ \_/ \| \_/ \ | \_/ \____\ \____/ \____\ \____\ \____/
ultimate-seed
is the ultimate full-stack AngularJS + Node.js/Express seed (batteries included!) that makes web developers insanely productive.
This project uses ultimate dependency library.
ultimate-seed
comes with many of popular, battle-tested modern web frameworks and libraries. All these parts are already wired together for you using best practices! :) Don't waste time writing boilerplate code.
- Angular
- AngularUI
- Barbeque
- Bootstrap
- Bower
- Browserify
- Express
- Font Awesome
- Grunt
- Handlebars
- jQuery
- JSHint
- Karma w/ Mocha
- LESS w/ LESS Hat
- Livereload
- Lodash (Underscore)
- Modernizr
- MongoDB w/ Mongoose
- Passport
- Passport-Facebook
- Passport-Google
- Passport-Twitter
- Redis w/ Hiredis
- SocketIO
- Source Maps
- Uglify
- Winston
Dependency | Installation |
---|---|
Node.js | download |
MongoDB | download |
Redis | download |
Bower | npm install bower -g |
Grunt | npm install grunt-cli -g |
Make sure both MongoDB
and Redis
servers running somewhere. (You can use free hosting services such as MongoHQ or MongoLab for MongoDB
and Redis To Go or RedisCloud for Redis
.) Then, update configuration information in config/{development,heroku,production}.json
.
If you find any reason not to use Redis
in your project, you can easily achieve it by following this instruction:
- Change the value of
session.store._use
tomongo
inconfig/{development,heroku,production}.json
. (This letsultimate-seed
use MongoDB as session backend.) - Comment out the line
ultimate.db.redis.connect(app.config.db.redis);
inserver/app.js
. (This prevents server connecting toRedis
server.)
Yeoman generator for ultimate-seed can be used to clone the seed project.
$ npm install -g yo
$ npm install -g generator-ultimate
$ yo ultimate
Download ultimate-seed
and install dependency modules:
$ git clone https://github.com/pilwon/ultimate-seed.git ultimate-seed
$ cd ultimate-seed
$ npm install && bower install
Now create seed
branch that tracks remote branch ultimate-seed/master
:
$ git remote add seed https://github.com/pilwon/ultimate-seed.git
$ git fetch seed
$ git checkout -b seed seed/master
Push a copy of seed
to origin/seed
:
$ git push origin seed
Merge seed
to master
branch:
$ git checkout master
$ git merge seed
$ npm install && bower install
Resolve merge conflicts then push to origin/master
:
$ git push
Grunt tasks to build your app:
$ grunt # start server
$ grunt build # jshint & build
$ grunt clean # clean grenerated files
- If you see the
Could not load the bindings file.
error message, please performnpm rebuild
then try again.
Unit Testing with Karma
TODO
End-to-End (E2E) Testing with Protractor
Protractor wraps around WebDriverJS, which is a javascript binding for Selenium-Webdriver.
Selenium-Webdriver is a browser automation framework. Tests are written with the WebDriver API, which communicates with a Selenium server to control the browser under test. - Protractor Getting Started Guide
Therefore, you need to first download and install Selenium standalone server. If you successfully performed npm install
, you will have ./node_modules/.bin/webdriver-manager
. You can download and install Selenium standalone server by the following command:
$ ./node_modules/.bin/webdriver-manager update
From then on, you can start the server via:
$ ./node_modules/.bin/webdriver-manager start
You need to have the Selenium server running before running E2E tests. Once the Selenium server is running, you should also start the application server (in another tab) because your tests will run against it:
$ grunt
While the application server is running, open another tab and run e2e tests using Protractor.
$ grunt test
Enjoy watching your tests running inside a real browser (Chrome by default). If you'd like to change Protractor configuration, check out config/test/protractor-e2e.conf.js
.
** TODO: Simplify the above steps so that it can be all done using one grunt command. **
First, prepare and optimize all files used in production environment:
$ grunt build
Then your app can be started in production mode using this command:
$ NODE_ENV=production node server
It is recommended to use a tool like forever to ensure your app running continuously:
$ npm install forever -g
$ NODE_ENV=production PORT=3000 forever start server
You can alternatively use a system-wide process control system such as Supervisor with the following configuration (supervisord.conf
):
[program:ultimate-3000]
directory = <absolute-path-of-project-root>
environment = NODE_ENV=production, PORT=3000
command = node server
autostart = true
autorestart = true
ultimate-seed
supports deployment of your app to Heroku servers.
- Modify
config/heroku.json
. - Comment out the following lines in
.gitignore
. */.cachebust
*/client/js/node_modules/bower_components/
*/client-built/
*/config/heroku.json
*/node_modules/
- Run
grunt build
to build the project. - Commit all files to a local git repository created at the project root.
- Add git remote pointing to Heroku:
* New Heroku app:
heroku create APPID
* Existing Heroku app:heroku git:remote -a APPID
- Set the environment variable:
heroku config:set NODE_ENV=heroku ERROR_PAGE_URL=http://APPID.herokuapp.com/404.html
- Enable websocket support:
heroku labs:enable websockets
- (Optional) Install MongoDB and Redis add-ons to the Heroku app.
ultimate-seed
reads environment variables attached by these add-ons. (Note: Add-on environment variables will override MongoDB/Redis configuration values inconfig/heroku.json
): * Mongo:heroku addons:add mongohq:sandbox
orheroku addons:add mongolab:sandbox
* Redis:heroku addons:add redistogo:nano
orheroku addons:add rediscloud:20
- Deploy application to Heroku using
git push heroku +master
- Deployed at http://APPID.herokuapp.com/
This is helpful when you need to debug problems on the production server. You can connect to REPL of the running server via UNIX socket. By default, it creates UNIX socket at /tmp/ultimate-repl but you can configure it in config/{development,heroku,production}.json
. In order to connect to it, simply run:
$ nc -U /tmp/ultimate-repl
ultimate>
or if you want readline's line editing and persistent history (i.e. using up/down arrow key to see the command history), then install rlwrap (on Mac, brew install rlwrap
) and run:
$ rlwrap nc -U /tmp/ultimate-repl
ultimate>
Once you are connected, you can evaluate Javascript expression.
ultimate> 3 + 3
6
ultimate>
For your convenience, several variables/functions are exposed. Try the followings:
ultimate> app // ultimate app object
ultimate> ld // lodash (underscore) object (couldn't use _ because it has special meaning in REPL i.e. the result of the last expression)
ultimate> ultimate // ultimate object that ultimate-seed utilizes
ultimate> showRoutes() // shows an array of all routes (e.g. [ ..., 'GET /api/user/features/:id', ...])
. ├── client/ │ ├── components/ │ ├── fonts/ │ │ ├── font-awesome/ │ │ └── glyphicons/ │ ├── js/ │ │ ├── {{module}}/ │ │ │ ├── controllers/ │ │ │ ├── directives/ │ │ │ ├── services/ │ │ │ ├── templates/ │ │ │ │ └── {{template}}.html │ │ │ └── index.js │ │ ├── node_modules/ │ │ │ ├── bower_components/ │ │ │ └── custom_components/ │ │ ├── app.js │ │ └── index.js │ └── less/ │ ├── _layouts/ │ ├── bootstrap/ │ ├── font-awesome/ │ ├── lesshat/ │ └── social-buttons/ ├── config/ │ ├── development.json │ ├── heroku.json │ ├── nginx.conf │ └── production.json ├── log/ ├── node_modules/ ├── server/ │ ├── controllers/ │ ├── lib/ │ ├── models/ │ ├── sockets/ │ ├── views/ │ │ ├── _helpers/ │ │ ├── _layouts/ │ │ │ └── default.hbs │ │ ├── _partials/ │ │ │ └── livereload.hbs │ │ ├── home/ │ │ ├── status/ │ │ └── empty.hbs │ ├── app.js │ ├── index.js │ ├── routes.js │ ├── socketio.js │ └── winston.js ├── static/ │ ├── img/ │ ├── 404.html │ ├── favicon.ico │ └── robots.txt ├── worker/ │ ├── task/ │ ├── index.js │ └── process.js ├── .bowerrc ├── .editorconfig ├── .jshintrc ├── .slugignore ├── Gruntfile.js ├── Procfile ├── bower.json ├── npm-scripts.js ├── package.json └── project.json
This is an issue with grunt-contrib-watch. You can fix it by increasing your system's max opened file limit. See this answer
NOTE: Even if ulimit
command on the shell gives you 'unlimited', you might still need to increase the max opened file limit.
If you are using node version manager n, you might come across the following error message when running grunt
:
Fatal error: Server ["/Users/username/path-to-ultimate-seed/server"] - Error: Could not load the bindings file. Tried:
→ /Users/username/path-to-ultimate-seed/node_modules/bcrypt/build/bcrypt_lib.node
→ /Users/username/path-to-ultimate-seed/node_modules/bcrypt/build/Debug/bcrypt_lib.node
...
→ /Users/username/path-to-ultimate-seed/node_modules/bcrypt/build/default/bcrypt_lib.node
→ /Users/username/path-to-ultimate-seed/node_modules/bcrypt/compiled/0.10.23/darwin/x64/bcrypt_lib.node
In order to fix it, run npm rebuild
. Then you will be able to run grunt
without seeing the above error message.
We welcome your pull requests to the dev
branch.
- Pilwon Huh (creator, maintainer)
- Brian Park (collaborator)
Thanks to all the other contributors as well! :)
The MIT License (MIT) Copyright (c) 2012-2013 Pilwon Huh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.