47pages-keystone 中文文档教程
47Pages Fork
KeystoneJS 的 47Pages 分支是必要的,原因有两个:
- Keystone is still in a stage of relatively unstable development
- The 47Pages site requires additional functionality tailored to its unique needs
也就是说,本地化更改与上游 Keystone 存储库保持同步很重要,因为那里的开发不断改进。 我们希望能够将这些更改拉入我们的分叉分支,同时保持我们生产版本的稳定性并保留为 47Pages 所做的自定义更改。
Branching model
在本地克隆 keystone-47pages 并设置上游来源:
git clone git@github.com:git@github.com:47pages/keystone.git
git remote add upstream git@github.com:JedWatson/keystone.git
要开发,请检查最新的开发分支(例如 47pages-0617-4f48821)。 第一个数字是分支创建的月份和日期,以便于按时间顺序排序。 第二个数字是此分支已根据其重新定位的最新上游提交的短 SHA1 哈希。 在进行更改时将提交添加到此分支。
当您准备好合并到生产分支时,您必须首先针对上游分支变基 47pages-prod! 这是为了确保我们的更改不会与官方存储库有太大差异。
git checkout master
git pull upstream master
git checkout 47pages-prod
git merge master
解决任何冲突。 检查从上游引入的更改是否一切正常。 请注意,与 47pages 相关的更改仅发生在以 47pages 为前缀的分支中 - 我们的 master 应该始终是原始的。
然后,只需将开发分支中的更改合并到生产中即可。 此时应该没有冲突。
git merge 47pages-date-sha1
git push origin 47pages-prod
最后,为未来的变化创建新的开发分支。 如果出现问题,旧的开发分支可以保留下来回滚,但不应在其中进行新的开发。
git checkout master
git rev-parse --short HEAD
git checkout 47pages-prod
git checkout -b 47pages-newdate-newsha1
KeystoneJS 是一个强大的新的 Node.js 内容管理系统和基于 express 和 mongoose 这使得创建复杂的网站和应用程序变得容易,并为您提供了一个漂亮的、自动生成的管理 UI。
要开始,请查看 keystonejs.com!
About
Keystone 为您提供:
- A simple way to create a dynamic web site or app with well-structured routes, templates and models
- A beautiful Admin UI based on the database models you define
- Enhanced
models
with additional field types and functionality, building on those natively supported by Mongoose - Out of the box session management and authentication
- An updates framework for managing data updates or initialisation
- Integration with Cloudinary for image uploading, storage and resizing
- Integration with Mandrill for sending emails easily
- Integration with Google Places for clever location fields
- Integration with Embedly for powerful video and rich media embedding tools
... 以及许多其他工具和实用程序,使创建复杂的网络应用程序变得更加容易。
使用我们的 Yeoman Generator 快速启动和运行 KeystoneJS,然后查看我们的入门指南和指南。 文档位于 keystonejs.com/docs/getting-started。
我们在 demo.keystonejs.com 有一个演示网站,您可以在其中试用 Keystone 管理 UI,并且您可以 阅读源代码 了解它是如何构建的。
如果您有想法或问题,请联系 KeystoneJS Google Group 或发送推文至 @KeystoneJS。
SydJS Website
Keystone 的主要贡献者位于澳大利亚悉尼,并且 KeystoneJS 是用 Javascript 编写的,因此使用它为悉尼 Javascript 社区创建一个站点是很自然的。
SydJS 网站 是比 Keystone 演示更复杂的项目的一个很好的例子,您可以 查看源代码 了解它是如何构建的。
我们还使用 Cordova、Backbone、Velocity.js 和 jQuery 编写了一个 SydJS Mobile App 来演示如何使用 Javascript针对 KeystoneJS 后端运行,为移动应用程序创建原生体验。 如需更多信息,包括我们的设计资源,请查看 SydJS Showbag。
如果您经营一个社区小组,请随时复制我们的网站和应用程序并将它们变成您自己的! 如果您愿意,我们很乐意听取您的意见。
Contributing
KeystoneJS 有远大的愿景,社区的支持是实现它的重要组成部分。
我们乐于听到有关 Keystone 和您使用它的项目的反馈,并且很乐意在 KeystoneJS Google Group 上提供建议 如果你卡住了。
如果可以,请通过报告问题、讨论想法或提交包含补丁和新功能的拉取请求来做出贡献。 我们尽最大努力在一两天内响应所有问题和拉取请求,并定期向 npm 发布补丁。
如果您要贡献代码,请尝试模仿现有的代码标准 - 我们非常严格地遵循 AirBNB 的 Javascript 风格指南,使用制表符缩进的例外。
Documentation
Keystone 文档在线托管在 keystonejs.com。 如果您处于离线状态,或者想要贡献文档并预览您的更改,您可以通过在 ./docs
文件夹中运行 node docs
在本地提供它们(您将还必须先运行 npm install
。这将在端口 8080 上启动文档站点。
Usage
查看 KeystoneJS 文档< /a> 了解如何使用 KeystoneJS。
Installation
开始使用 Keystone 最简单的方法是使用 Yeoman 生成器。
要安装它,请在终端中键入以下内容:
npm install -g yo
npm install -g generator-keystone
然后,创建一个新文件夹对于你的项目,在你的终端中输入以下内容:
yo keystone
这将根据你选择的选项创建一个新项目,并从 npm 安装所需的包。
安装完成后,运行此启动 Keystone 的命令:
node keystone
或者,要在现有项目中包含 Keystone 或从头开始(没有 Yeoman),请在 de 中指定
数组,然后从您的终端运行 keystone: "0.2.x"
在您的 package.json
文件中添加 pendenciesnpm install
。
Example application script (keystone.js)
在默认模式下运行,Keystone 会处理使用 Express 配置应用程序、连接到 MongoDB 数据库以及启动 Web 服务器所需的一切。
以下是您的 keystone.js
(或 app.js
等)文件的示例:
var keystone = require('keystone');
keystone.init({
'name': 'My Project',
'brand': 'Project',
'favicon': 'public/favicon.ico',
'less': 'public',
'static': 'public',
'views': 'templates/views',
'view engine': 'jade',
'auth': true,
'user model': 'User',
'cookie secret': '--- your secret ---',
'auto update': true,
'emails': 'templates/emails',
'mandrill api key': '--- your api key ---',
'email rules': { find: '/images/', replace: (keystone.get('env') != 'production') ? 'http://localhost:3000/images/' : 'http://www.keystonejs.com/images/email/' },
'cloudinary config': { cloud_name: '--- your cloud name ---', api_key: '--- your api key ---', api_secret: '--- your api secret ---' }
});
keystone.import('models');
keystone.set('routes', require('./routes'));
keystone.start();
Configuration
配置变量可以在对象中传递给 keystone.init
方法,或者可以在 keystone.start
之前的任何时间设置 使用 keystone.set(key, value)
调用。 这允许更灵活的执行顺序(例如,如果您在您的 路由,您可以在配置列表后设置路由,如上例所示)。
请参阅 KeystoneJS 配置文档,了解可用的详细信息和示例 配置选项。
要了解如何使用这些设置以及 Express 应用程序如何初始化,请参阅 Keystone.prototype.start
<代码>/index.js。
Database field types
Keystone 建立在 mongo 提供的基本数据类型之上,允许您轻松添加丰富的、 应用程序模型的功能字段。
您可以在模型上获得辅助方法来轻松处理每种字段类型(例如 格式化日期或数字、调整图像大小、获取可用选项的数组 用于选择字段,或使用 Google 的 Places API 来改进地址)以及一个漂亮的, 用于编辑数据的响应式管理 UI。
有关各种字段类型的详细信息和示例,请参阅 KeystoneJS 数据库文档, 以及如何在您的应用程序中设置和使用数据库模型。
Keystone 的字段类型包括:
- Boolean
- Text
- Textarea
- Url
- Html
- Color
- Date
- Datetime
- Key
- Number
- Money
- Select
- Markdown
- Name
- Password
- Location
- CloudinaryImage
- CloudinaryImages
- LocalFile
- S3 File
- Embedly
Keystone 还有关系字段,用于管理一对多和多对多 不同模型之间的关系。
Running KeystoneJS in Production
当您将 KeystoneJS 应用程序部署到生产环境时,请务必将您的 ENV
环境变量设置为 production
。 您可以通过在 .env
文件中设置 NODE_ENV=production
来完成此操作,该文件由 dotenv。
设置您的环境可以启用某些功能,包括模板缓存、更简单的错误报告和 html 缩小,这些功能在生产中很重要,但在开发中很烦人。
Linking Keystone for Development and Testing
如果你想针对 KeystoneJS 的 master
分支(或针对你自己的分支)进行测试或开发,而不是在 npm 上发布的版本,你只需要检查一下然后使用 npm link
将其链接到您的项目。 在 Mac OS 上,这是这样完成的:
- Checkout KeystoneJS locally, e.g. to
~/Development/KeystoneJS
- From the KeystoneJS directory, run
sudo npm link
(you will need to enter your system password) - From your project directory, e.g.
~/Development/MySite
(the one with yourpackage.json
file in it) runnpm link keystone
. This will create a link between~/Development/MySite/node_modules/keystone
and~/Development/KeystoneJS
.
然后 require('keystone')
通常在您的应用程序中 - 将使用开发副本。 请注意,运行 npm update
将忽略已发布的新版本的 keystone。
要返回使用来自 npm 的已发布版本的 KeystoneJS,请从您的项目目录运行 npm unlink keystone
,然后运行 npm install
。
Advanced Usage
也可以将 keystone 集成到现有的 express 应用程序中,而无需使用 start
方法。 这对您的应用程序的假设较少,并提供了很大的灵活性。
在定义任何列表之前,您可以向 Keystone 的 connect
函数提供一个 mongoose
或 express
实例。 connect
返回 this
因此您可以在 require
调用中执行此操作。
keystone.static(app)
将 Keystone 的静态路由处理中间件添加到 Express 应用程序。 最好在应用程序的其他静态资产之后、任何动态逻辑(例如 cookie 解析、会话身份验证、正文解析等)之前执行此操作
keystone.routes(app);
将 Keystone 的动态路由添加到Express 应用路由器。 这可以在您的应用程序的路由定义之前或之后完成,尽管如果它们在之后出现,您可以明确锁定或用您自己的路由替换 Keystone 路由(所以要小心)。
Mounting Keystone as a sub-app or creating a node module out of your Keystone project
您可能还只想将 Keystone 作为一个子应用程序安装在更大的 express 应用程序中,并且仍然让 Keystone 运行其完整的配置和设置例程,但不启动其自己的 http 服务器(即 embedded
模式)。
…或者您可能还想将 Keystone 项目转换为可以通过 npm link
或 npm install
轻松嵌入的节点模块。
下面的详细示例将涵盖创建节点模块以及将 Keystone 应用程序作为子应用程序安装在更大的基于 Express 的应用程序中。
假设你有一个解决方案分解成这样的结构
/client
/content
/server
......其中 /client
是一些超级棒的大型单页客户端应用程序,用 AngularJS 或 Polymer, /server
是一个强大的后端驱动通过 StrongLoop 或其他基于 Express 的东西提供数据,也许是 / 的构建版本client
,最后是 /content
是一个 Keystone 应用程序,您只想将其用于出色的 CMS 建模、查询和自动管理界面。 换句话说,您认为 Keystone 擅长内容相关的数据管理和电子邮件内容,但并不真正喜欢它的前端内容(管理应用程序除外)。
在此示例中,所有三个项目都是自己的节点应用程序,具有自己的 package.json
文件。 此示例中的 /content
应用程序可能是您使用 Keystone 的 yeoman 生成器 的结果,然后从 /routes
和 /templates
中删除大部分内容,只使用 /models
和 /updates
以及电子邮件的东西。
然后,您希望将 /content
应用程序作为链接模块集成到 /server
中,并将其作为子应用程序安装在路径 /content
。
**您的 /content/keystone.js
文件看起来像这样: **
// Simulate config options from your production environment by
// customising the .env file in your project's root folder.
require('dotenv')().load();
// Require keystone
var keystone = require('keystone');
// Initialise Keystone with your project's configuration.
// See http://keystonejs.com/guide/config for available options
// and documentation.
keystone.init({
'name': 'Your App Name',
'brand': 'Your App Name',
'emails': 'templates/emails',
'auto update': true,
'session': true,
'auth': true,
'user model': 'User',
'cookie secret': 'your cookie secret'
});
// Load your project's Models
keystone.import('models');
// Setup common locals for your emails. The following are required by Keystone's
// default email templates, you may remove them if you're using your own.
keystone.set('email locals', {
logo_src: '/images/logo-email.gif',
logo_width: 194,
logo_height: 76,
theme: {
email_bg: '#f9f9f9',
link_color: '#2697de',
buttons: {
color: '#fff',
background_color: '#2697de',
border_color: '#1a7cb7'
}
}
});
// Setup replacement rules for emails, to automate the handling of differences
// between development a production.
// Be sure to update this rule to include your site's actual domain, and add
// other rules your email templates require.
keystone.set('email rules', [{
find: '/images/',
replace: (keystone.get('env') == 'production') ? 'http://www.your-server.com/images/' : 'http://localhost:3000/images/'
}, {
find: '/keystone/',
replace: (keystone.get('env') == 'production') ? 'http://www.your-server.com/keystone/' : 'http://localhost:3000/keystone/'
}]);
// Load your project's email test routes
keystone.set('email tests', require('./routes/emails'));
// Configure the navigation bar in Keystone's Admin UI
keystone.set('nav', {
'posts': ['posts', 'post-categories'],
'galleries': 'galleries',
'enquiries': 'enquiries',
'users': 'users'
});
module.exports = keystone;
注意最后一行。 无需通过 keystone.start()
启动 keystone 服务器,您只需导出 keystone 对象即可。 这将使您可以轻松地将此模块嵌入到另一个应用程序中。
您可能还想制作一个与 keystone.js
处于同一级别的 app.js
文件,它所做的只是需要这个导出的对象并启动服务器。 如果您仍然想破解您的模型并以孤立的方式测试它们,这将很有用。
app.js
:
var keystone = require('./keystone');
keystone.start();
可嵌入 Keystone 项目的最后一步设置是稍微修改 package.json
文件以包含 main
值。 这是下一步工作所必需的。
package.json
:
{
"name": "your-app-content",
"version": "0.0.0",
"private": true,
"dependencies": {
"keystone": "~0.2.6",
"async": "~0.2.9",
"underscore": "~1.5.2",
"dotenv": "0.0.3"
},
"engines": {
"node": ">=0.10.22",
"npm": ">=1.3.14"
},
"main": "keystone.js",
"scripts": {
"start": "app.js"
}
}
现在要在开发过程中将 Keystone 项目作为 node_module 嵌入到您的 /server
应用程序中,只需运行 npm link< /code> 来自
/content
项目的根文件夹,然后是 /server
应用根文件夹中的 npm link your-app-content
(注意:在执行第二个 npm link
时,将 your-app-content
替换为 /content
应用在其 中的实际名称package.json
文件)。
所有这些工作的下一步是在服务器应用程序中使用 keystone.mount
。
/server
中的 app.js
示例:
var express = require('express'),
app = express();
app.keystone = require('your-app-content');
//...do your normal express setup stuff, add middleware and routes (but not static content or error handling middleware yet)
app.keystone.mount('/content', app, function() {
//put your app's static content and error handling middleware here and start your server
});
假设您使用端口 3000
来运行上面的示例,您可以然后打开浏览器访问 http://localhost:3000/content/keystone
以访问您的 Keystone 管理界面(由您自己的更高级别的应用程序托管)。
像我们上面那样直接在您的应用程序上引用 keystone 对象意味着您现在可以在您的应用程序中使用来自您的 Keystone 模型的所有强大的查询工具,也许在一些非常安全的 ACL 管理路由或其他类似的有趣东西之后。
最后,如果您正在在您的 Keystone 项目中使用 dotenv
将您的配置存储在 .env
文件中,您还需要创建一个.env
文件位于 /server
项目的根级别。
现在你有了一个功能齐全的可嵌入 KeystoneJS 模块,你可以在后端、前端和内容的开发和测试之间实现良好的关注点分离。
Thanks
KeystoneJS 是一个免费的开源社区驱动项目。 感谢我们的许多贡献者和users 让它变得很棒。
感谢以下公司和项目,我们在 KeystoneJS 的制作过程中使用或从中获得灵感:(
- Node.js
- Thinkmill
- ExpressJS
- MongoDB
- Mongoose
- jQuery
- Underscore
- Bootstrap
- Amazon
- Heroku
- Cloudinary
- Embedly
- Yusuke Kamiyamane
License
麻省理工学院许可)
版权所有 (c) 2014 Jed Watson
特此免费授予任何获得许可的人 此软件和相关文档文件的副本( “软件”),不受限制地处理软件,包括 但不限于使用、复制、修改、合并、发布、 分发、再许可和/或出售软件的副本,以及 允许向其提供软件的人这样做,但须遵守 下列条件:
上述版权声明和本许可声明应 包含在软件的所有副本或重要部分中。
本软件按“原样”提供,不提供任何形式的保证, 明示或暗示的,包括但不限于 适销性、特定用途的适用性和非侵权性。 在任何情况下,作者或版权持有人均不对任何 索赔、损害赔偿或其他责任,无论是在合同行为中, 侵权行为或其他由以下原因引起、由其引起或与之相关的行为 软件或软件的使用或其他交易。
47Pages Fork
The 47Pages fork of KeystoneJS is necessary for two reasons:
- Keystone is still in a stage of relatively unstable development
- The 47Pages site requires additional functionality tailored to its unique needs
That being said, it is important that localized changes be kept in sync with the upstream Keystone repository, as development there is continuously improving. We want to be able to pull down those changes into our forked branch, while maintaining stability on our production release and retaining the custom changes made for 47Pages.
Branching model
Clone keystone-47pages locally and set the upstream origin:
git clone git@github.com:git@github.com:47pages/keystone.git
git remote add upstream git@github.com:JedWatson/keystone.git
To develop, checkout the latest development branch (e.g. 47pages-0617-4f48821). The first number is the month and date of the branch's creation, to allow for easy chronological sorting. The second number is the short SHA1 hash of the latest upstream commit that this branch has been rebased against. Add commits to this branch as you make changes.
When you are ready to merge into the production branch, you must first rebase 47pages-prod against the upstream fork! This is to ensure that our changes do not diverge too much from the official repository.
git checkout master
git pull upstream master
git checkout 47pages-prod
git merge master
Resolve any conflicts. Check that everything is working okay with the changes pulled in from upstream. Note that 47pages-related changes only ever happen in branches prefixed with 47pages - our master should always be pristine.
Then, simply merge the changes in your development branch into production. There should be no conflicts at this point.
git merge 47pages-date-sha1
git push origin 47pages-prod
Finally, create the new development branch for future changes. Old development branches can stay around to rollback to if something breaks, but no new development should take place in them.
git checkout master
git rev-parse --short HEAD
git checkout 47pages-prod
git checkout -b 47pages-newdate-newsha1
KeystoneJS is a powerful new Node.js content management system and web app framework built on express and mongoose that makes it easy to create sophisticated web sites and apps, and gives you a beautiful, auto-generated Admin UI.
To get started, check out keystonejs.com!
About
Keystone gives you:
- A simple way to create a dynamic web site or app with well-structured routes, templates and models
- A beautiful Admin UI based on the database models you define
- Enhanced
models
with additional field types and functionality, building on those natively supported by Mongoose - Out of the box session management and authentication
- An updates framework for managing data updates or initialisation
- Integration with Cloudinary for image uploading, storage and resizing
- Integration with Mandrill for sending emails easily
- Integration with Google Places for clever location fields
- Integration with Embedly for powerful video and rich media embedding tools
… plus a lot of other tools and utilities to make creating complex web apps easier.
Use our Yeoman Generator to get up and running with KeystoneJS quickly, then check out our getting started guide & docs at keystonejs.com/docs/getting-started.
We have a demo website at demo.keystonejs.com where you can play with the Keystone Admin UI, and you can read the source to see how it was built.
If you have ideas or questions, get in touch on the KeystoneJS Google Group or tweet at @KeystoneJS on twitter.
SydJS Website
The primary contributors to Keystone are based in Sydney, Australia and KeystoneJS is written in Javascript, so it was only natural to create a site for the Sydney Javascript Community using it.
The SydJS Website is a great example of a more sophisticated project than the Keystone Demo, and you can view the source code to see how it was built.
We have also written a SydJS Mobile App with Cordova, Backbone, Velocity.js and jQuery to demonstrate how Javascript can be used to create a native experience for mobile apps, running against a KeystoneJS back-end. For more, including our design resources, check out the SydJS Showbag.
If you run a community group, please feel free to copy our site and app and make them your own! And if you do, we'd love to hear from you.
Contributing
KeystoneJS has a big vision, and the support of the community is an important part of making it a reality.
We love to hear feedback about Keystone and the projects you're using it for, and are happy to give advice on the KeystoneJS Google Group if you get stuck.
If you can, please contribute by reporting issues, discussing ideas, or submitting pull requests with patches and new features. We do our best to respond to all issues and pull requests within a day or two, and make patch releases to npm regularly.
If you're going to contribute code, please try and mimic the existing code standards - we follow AirBNB's Javascript Style Guide fairly closely, with the exception of using tab indentation.
Documentation
The Keystone docs are hosted online at keystonejs.com. If you are offline, or would like to contribute to the docs and preview your changes, you can serve them locally by running node docs
within the ./docs
folder (you will also have to run npm install
first. This will start the docs site on port 8080.
Usage
Check out the KeystoneJS Documentation for a walk-through on how to use KeystoneJS.
Installation
The easiest way to get started with Keystone is to use the Yeoman generator.
To install it, type the following in your terminal:
npm install -g yo
npm install -g generator-keystone
Then, create a new folder for your project and from it, type the following in your terminal:
yo keystone
This will create a new project based on the options you select, and install the required packages from npm.
After the intallation is complete, run this command to start Keystone:
node keystone
Alternatively, to include Keystone in an existing project or start from scratch (without Yeoman), specify keystone: "0.2.x"
in the dependencies
array in your package.json
file, and run npm install
from your terminal.
Then read through the Documentation and the Example Projects to understand how to use it.
Example application script (keystone.js)
Running in default mode, Keystone takes care of everything required to configure your application with Express, connect to your MongoDB database, and start the web server.
Here is an example of what your keystone.js
(or app.js
, etc) file may look like:
var keystone = require('keystone');
keystone.init({
'name': 'My Project',
'brand': 'Project',
'favicon': 'public/favicon.ico',
'less': 'public',
'static': 'public',
'views': 'templates/views',
'view engine': 'jade',
'auth': true,
'user model': 'User',
'cookie secret': '--- your secret ---',
'auto update': true,
'emails': 'templates/emails',
'mandrill api key': '--- your api key ---',
'email rules': { find: '/images/', replace: (keystone.get('env') != 'production') ? 'http://localhost:3000/images/' : 'http://www.keystonejs.com/images/email/' },
'cloudinary config': { cloud_name: '--- your cloud name ---', api_key: '--- your api key ---', api_secret: '--- your api secret ---' }
});
keystone.import('models');
keystone.set('routes', require('./routes'));
keystone.start();
Configuration
Config variables can be passed in an object to the keystone.init
method, or can be set any time before keystone.start
is called using keystone.set(key, value)
. This allows for a more flexible order of execution (e.g. if you refer to Lists in your routes, you can set the routes after configuring your Lists, as in the example above).
See the KeystoneJS configuration documentation for details and examples of the available configuration options.
To understand how these settings are used, and how the Express application initialised, see Keystone.prototype.start
in /index.js
.
Database field types
Keystone builds on the basic data types provided by mongo and allows you to easily add rich, functional fields to your application's models.
You get helper methods on your models for dealing with each field type easily (such as formatting a date or number, resizing an image, getting an array of the available options for a select field, or using Google's Places API to improve addresses) as well as a beautiful, responsive admin UI to edit your data with.
See the KeystoneJS database documentation for details and examples of the various field types, as well as how to set up and use database models in your application.
Keystone's field types include:
- Boolean
- Text
- Textarea
- Url
- Html
- Color
- Date
- Datetime
- Key
- Number
- Money
- Select
- Markdown
- Name
- Password
- Location
- CloudinaryImage
- CloudinaryImages
- LocalFile
- S3 File
- Embedly
Keystone also has Relationship fields for managing one-to-many and many-to-many relationships between different models.
Running KeystoneJS in Production
When you deploy your KeystoneJS app to production, be sure to set your ENV
environment variable to production
. You can do this by setting NODE_ENV=production
in your .env
file, which gets handled by dotenv.
Setting your environment enables certain features, including template caching, simpler error reporting and html minification, that are important in production but annoying in development.
Linking Keystone for Development and Testing
If you want to test or develop against the master
branch of KeystoneJS (or against your own branch), rather than a published version on npm, you just need to check it out then use npm link
to link it to your project. On Mac OS, this is done like this:
- Checkout KeystoneJS locally, e.g. to
~/Development/KeystoneJS
- From the KeystoneJS directory, run
sudo npm link
(you will need to enter your system password) - From your project directory, e.g.
~/Development/MySite
(the one with yourpackage.json
file in it) runnpm link keystone
. This will create a link between~/Development/MySite/node_modules/keystone
and~/Development/KeystoneJS
.
Then require('keystone')
normally in your app - the development copy will be used. Note that running npm update
will ignore new versions of keystone that have been published.
To go back to using a published version of KeystoneJS from npm, from your project directory, run npm unlink keystone
then npm install
.
Advanced Usage
It is also possible to integrate keystone into an existing express app, without using the start
method. This assumes less about your app and provides a lot of flexibility.
You can provide a mongoose
or express
instance to Keystone's connect
function before defining any lists. connect
returns this
so you can do this in the require
call.
keystone.static(app)
adds Keystone's static route-handling middleware to the Express app. It's a good idea to do this after your application's other static assets, before any dynamic logic (e.g. cookie parsing, session authentication, body parsing, etc)
keystone.routes(app);
adds Keystone's dynamic routes to the Express app router. This can be done before or after your application's routes are defined, although if they come after, you can explicitly lock down or replace Keystone routes with your own (so be careful).
Mounting Keystone as a sub-app or creating a node module out of your Keystone project
You may also just want to mount Keystone as a sub-app within a larger express app, and still let Keystone run its full configuration and setup routine but not start its own http server (i.e. embedded
mode).
…Or you might also want to turn a Keystone project into a node module that can be embedded easily via npm link
or npm install
.
The following detailed example will cover both creating a node module as well as mounting the Keystone app as a sub-app within a larger Express based application.
Let's say you have a solution broken out into a structure like so…
/client
/content
/server
…where /client
is some super awesome large scale single page client app written in AngularJS or Polymer, /server
is a whiz-bang back end powered by StrongLoop or something else based on Express that serves up the data and maybe the built version of /client
, and finally /content
is a Keystone app that you want to use just for the awesome CMS modeling, querying, and automatic admin interface. In other words, you think Keystone is great at the content related data management and email stuff but don't really love its front end stuff (other than the admin app).
In this example, all three projects are their own node apps with their own package.json
files. The /content
app in this example might be the result of you using Keystone's yeoman generator and then ripping out most of the stuff from /routes
and /templates
and just using /models
and /updates
and the email stuff.
You then want to integrate the /content
app as a linked module inside of /server
and mount it as a sub-app at the path /content
.
**Your /content/keystone.js
file would look something like this: **
// Simulate config options from your production environment by
// customising the .env file in your project's root folder.
require('dotenv')().load();
// Require keystone
var keystone = require('keystone');
// Initialise Keystone with your project's configuration.
// See http://keystonejs.com/guide/config for available options
// and documentation.
keystone.init({
'name': 'Your App Name',
'brand': 'Your App Name',
'emails': 'templates/emails',
'auto update': true,
'session': true,
'auth': true,
'user model': 'User',
'cookie secret': 'your cookie secret'
});
// Load your project's Models
keystone.import('models');
// Setup common locals for your emails. The following are required by Keystone's
// default email templates, you may remove them if you're using your own.
keystone.set('email locals', {
logo_src: '/images/logo-email.gif',
logo_width: 194,
logo_height: 76,
theme: {
email_bg: '#f9f9f9',
link_color: '#2697de',
buttons: {
color: '#fff',
background_color: '#2697de',
border_color: '#1a7cb7'
}
}
});
// Setup replacement rules for emails, to automate the handling of differences
// between development a production.
// Be sure to update this rule to include your site's actual domain, and add
// other rules your email templates require.
keystone.set('email rules', [{
find: '/images/',
replace: (keystone.get('env') == 'production') ? 'http://www.your-server.com/images/' : 'http://localhost:3000/images/'
}, {
find: '/keystone/',
replace: (keystone.get('env') == 'production') ? 'http://www.your-server.com/keystone/' : 'http://localhost:3000/keystone/'
}]);
// Load your project's email test routes
keystone.set('email tests', require('./routes/emails'));
// Configure the navigation bar in Keystone's Admin UI
keystone.set('nav', {
'posts': ['posts', 'post-categories'],
'galleries': 'galleries',
'enquiries': 'enquiries',
'users': 'users'
});
module.exports = keystone;
Notice the last line. Instead of starting the keystone server via keystone.start()
you simply export the keystone object. This will allow you to easily embed this module in another application.
You may also want to make an app.js
file at the same level as keystone.js
the does nothing more than require this exported object and starts the server. This is useful if you still want to hack on your models and test them in an isolated manner.
app.js
:
var keystone = require('./keystone');
keystone.start();
The last piece of the setup for your embeddable Keystone project is to slightly modify the package.json
file to include a main
value. This is needed for the next step to work.
package.json
:
{
"name": "your-app-content",
"version": "0.0.0",
"private": true,
"dependencies": {
"keystone": "~0.2.6",
"async": "~0.2.9",
"underscore": "~1.5.2",
"dotenv": "0.0.3"
},
"engines": {
"node": ">=0.10.22",
"npm": ">=1.3.14"
},
"main": "keystone.js",
"scripts": {
"start": "app.js"
}
}
Now to embed the Keystone project into your /server
app as a node_module during development, just run npm link
from within the /content
project's root folder, followed by npm link your-app-content
in the /server
app's root folder (note: when doing the second npm link
, replace your-app-content
with the actual name of your /content
app within its package.json
file).
The next step for all this to work is to use keystone.mount
in the server app.
Example app.js
in /server
:
var express = require('express'),
app = express();
app.keystone = require('your-app-content');
//...do your normal express setup stuff, add middleware and routes (but not static content or error handling middleware yet)
app.keystone.mount('/content', app, function() {
//put your app's static content and error handling middleware here and start your server
});
Assuming you are using port 3000
to run the above example, you could then open a browser to http://localhost:3000/content/keystone
to access your Keystone admin interface (hosted from your own higher level application).
Putting a reference to the keystone object directly on your app like we did above means you can now use all the powerful querying tools from your Keystone models in your app, perhaps behind some ridiculously secure ACL managed routes or something else fun like that.
And finally, if you are using dotenv
in your Keystone project to store your config in a .env
file, you will also need to create a .env
file at the root level of the /server
project.
Now you have a fully functioning embeddable KeystoneJS module and you can achieve good separation of concerns between the development and testing of the back-end, the front-end, and the content.
Thanks
KeystoneJS is a free and open source community-driven project. Thanks to our many contributors and users for making it great.
Thanks to the following companies and projects whose work we have used or taken inspiration from in the making of KeystoneJS:
- Node.js
- Thinkmill
- ExpressJS
- MongoDB
- Mongoose
- jQuery
- Underscore
- Bootstrap
- Amazon
- Heroku
- Cloudinary
- Embedly
- Yusuke Kamiyamane
License
(The MIT License)
Copyright (c) 2014 Jed Watson
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.