├── badges
└── npm-audit-badge.svg
├── modules
├── asset
│ ├── index.js
│ └── ui
│ │ └── src
│ │ ├── index.scss
│ │ └── index.js
├── two-column-widget
│ ├── views
│ │ └── widget.html
│ └── index.js
├── @apostrophecms
│ ├── express
│ │ └── index.js
│ ├── home-page
│ │ ├── views
│ │ │ └── page.html
│ │ └── index.js
│ ├── page
│ │ ├── views
│ │ │ └── notFound.html
│ │ └── index.js
│ ├── global
│ │ └── index.js
│ ├── template
│ │ └── views
│ │ │ └── outerLayout.html
│ └── admin-bar
│ │ └── index.js
├── default-page
│ ├── views
│ │ └── page.html
│ └── index.js
├── staff-member
│ └── index.js
└── program
│ └── index.js
├── .eslintignore
├── .eslintrc
├── deployment
├── README
├── settings.staging
├── migrate
├── rsync_exclude.txt
├── stop
├── settings
├── dependencies
└── start
├── Dockerfile
├── .gitignore
├── README.md
├── local.example.js
├── lib
└── area.js
├── LICENSE
├── package.json
├── scripts
├── sync-down
└── sync-up
├── app.js
├── views
└── layout.html
└── public
└── images
└── apos-dark.svg
/badges/npm-audit-badge.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/modules/asset/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /public/apos-frontend
2 | /data/temp
3 | /apos-build
--------------------------------------------------------------------------------
/modules/asset/ui/src/index.scss:
--------------------------------------------------------------------------------
1 | .rl-rte p {
2 | margin-bottom: 10px;
3 | }
--------------------------------------------------------------------------------
/modules/asset/ui/src/index.js:
--------------------------------------------------------------------------------
1 | export default () => {
2 | console.log('👋 🌏');
3 | };
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "apostrophe"
4 | ],
5 | "globals": {
6 | "apos": true
7 | },
8 | "rules": {
9 | "no-var": "error",
10 | "no-console": 0
11 | }
12 | }
--------------------------------------------------------------------------------
/deployment/README:
--------------------------------------------------------------------------------
1 | This is a deployment folder for use with Stagecoach.
2 |
3 | You don't have to use Stagecoach.
4 |
5 | It's just a neat solution for deploying node apps.
6 |
7 | See:
8 |
9 | http://github.com/punkave/stagecoach
10 |
--------------------------------------------------------------------------------
/modules/two-column-widget/views/widget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% area data.widget, 'one' %}
4 |
5 |
6 | {% area data.widget, 'two' %}
7 |
8 |
--------------------------------------------------------------------------------
/deployment/settings.staging:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Settings specific to the 'master' deployment target.
4 | # USER is the ssh user, SERVER is the ssh host. USER should
5 | # match the USER setting in /opt/stagecoach/settings on
6 | # the server
7 |
8 | USER=nodeapps
9 | SERVER=staging.apos.dev
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:carbon
2 |
3 | # Create app directory
4 | RUN mkdir -p /app
5 | WORKDIR /app
6 |
7 | # Bundle app source
8 | COPY . /app
9 | RUN npm install
10 |
11 | # Mount persistent storage
12 | VOLUME /app/data
13 | VOLUME /app/public/uploads
14 |
15 | EXPOSE 3000
16 | CMD [ "npm", "start" ]
17 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/express/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | options: {
3 | session: {
4 | secret: '4445faf16add86a'
5 | },
6 | apiKeys: {
7 | q7vKZQuqkWf: {
8 | // The user role associated with this key
9 | role: 'admin'
10 | }
11 | }
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/modules/default-page/views/page.html:
--------------------------------------------------------------------------------
1 | {#
2 | This is an example home page template. It inherits and extends a layout template
3 | that lives in the top-level views/ folder for convenience
4 | #}
5 |
6 | {% extends "layout.html" %}
7 |
8 | {% block main %}
9 | {% area data.page, 'main' %}
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/deployment/migrate:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Run any necessary database migration tasks that should happen while the
4 | # site is paused here.
5 | #
6 | # We don't have any, 3.x policy is safe migrations only. -Tom
7 |
8 | export NODE_ENV=production
9 |
10 | # node app @apostrophecms/migration:migrate
11 | #
12 | #echo "Site migrated"
13 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/home-page/views/page.html:
--------------------------------------------------------------------------------
1 | {#
2 | This is an example home page template. It inherits and extends a layout template
3 | that lives in the top-level views/ folder for convenience
4 | #}
5 |
6 | {% extends "layout.html" %}
7 |
8 | {% block main %}
9 |
10 | {% area data.page, 'main' %}
11 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/page/views/notFound.html:
--------------------------------------------------------------------------------
1 | {#
2 | Use this template to build out your 404 error pages. Like page templates,
3 | it inherits a global layout.
4 | #}
5 |
6 | {% extends "layout.html" %}
7 |
8 | {% block title %}404 - Page not found{% endblock %}
9 |
10 | {% block main %}
11 | We're sorry. We couldn't find the page you're looking for.
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/global/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | fields: {
3 | add: {
4 | _footerLinks: {
5 | label: 'Footer Links',
6 | type: 'relationship',
7 | withType: '@apostrophecms/page'
8 | }
9 | },
10 | group: {
11 | footer: {
12 | label: 'Footer',
13 | fields: [ '_footerLinks' ]
14 | }
15 | }
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/page/index.js:
--------------------------------------------------------------------------------
1 | // This configures the @apostrophecms/pages module to add a "home" page type to the
2 | // pages menu
3 |
4 | module.exports = {
5 | options: {
6 | types: [
7 | {
8 | name: 'default-page',
9 | label: 'Default'
10 | },
11 | {
12 | name: '@apostrophecms/home-page',
13 | label: 'Home'
14 | }
15 | ]
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/template/views/outerLayout.html:
--------------------------------------------------------------------------------
1 | {#
2 | This file extends Apostrophe's outerLayoutBase template, which we don't recommend
3 | overriding directly. Changes in this file, if any, are usually block overrides to
4 | modify the outer chrome, outside the main content area of the page. Most of the
5 | time you should just edit `layout.html` in the top level `views/` folder.
6 | #}
7 |
8 | {% extends "outerLayoutBase.html" %}
9 |
10 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/admin-bar/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | options: {
3 | groups: [
4 | {
5 | name: 'media',
6 | label: 'Media',
7 | items: [
8 | '@apostrophecms/image',
9 | '@apostrophecms/file',
10 | '@apostrophecms/image-tag',
11 | '@apostrophecms/file-tag'
12 | ]
13 | },
14 | {
15 | name: 'pieces',
16 | label: 'Content',
17 | items: [
18 | 'article'
19 | ]
20 | }
21 | ]
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/modules/@apostrophecms/home-page/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | options: {
3 | label: 'Home Page',
4 | pluralLabel: 'Home Pages'
5 | },
6 | fields: {
7 | add: {
8 | main: {
9 | type: 'area',
10 | contextual: true,
11 | options: {
12 | widgets: require('../../../lib/area').fullConfig
13 | }
14 | }
15 | },
16 | group: {
17 | basics: {
18 | label: 'Basics',
19 | fields: [
20 | 'title',
21 | 'main'
22 | ]
23 | }
24 | }
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/deployment/rsync_exclude.txt:
--------------------------------------------------------------------------------
1 | # List files and folders that shouldn't be deployed (such as data folders and runtime status files) here.
2 | # In our projects .git and .gitignore are good candidates, also 'data' which contains persistent files
3 | # that are *not* part of deployment. A good place for things like data/port, data/pid, and any
4 | # sqlite databases or static web content you may need
5 | data
6 | temp
7 | public/uploads
8 | public/apos-frontend
9 | .git
10 | .gitignore
11 | # We don't deploy these anymore, instead we always 'npm install' to ensure
12 | # that any compiled C++ modules are built for the right architecture
13 | node_modules
14 |
--------------------------------------------------------------------------------
/modules/default-page/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extend: '@apostrophecms/page-type',
3 | options: {
4 | label: 'Default Page',
5 | pluralLabel: 'Default Pages'
6 | },
7 | fields: {
8 | add: {
9 | main: {
10 | type: 'area',
11 | options: {
12 | widgets: require('../../lib/area').fullConfig
13 | }
14 | }
15 | },
16 | group: {
17 | basics: {
18 | label: 'Basics',
19 | fields: [
20 | 'title',
21 | 'visibility'
22 | ]
23 | },
24 | main: {
25 | label: 'Main',
26 | fields: [ 'main' ]
27 | }
28 | }
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/modules/two-column-widget/index.js:
--------------------------------------------------------------------------------
1 | const areaConfig = require('../../lib/area').basicConfig;
2 |
3 | module.exports = {
4 | extend: '@apostrophecms/widget-type',
5 | options: {
6 | label: 'Two Column',
7 | icon: 'pillar'
8 | },
9 | fields: {
10 | add: {
11 | one: {
12 | type: 'area',
13 | contextual: true,
14 | options: {
15 | widgets: areaConfig
16 | }
17 | },
18 | two: {
19 | type: 'area',
20 | contextual: true,
21 | options: {
22 | widgets: areaConfig
23 | }
24 | }
25 | }
26 | },
27 | icons: {
28 | pillar: 'Pillar'
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore vim swapfiles
2 | *.swp
3 | /storybook-static
4 | /public/apos-frontend
5 | /apos-build
6 | /apos-frontend
7 | /locales
8 | npm-debug.log
9 | /data
10 | /public/uploads
11 | /public/apos-minified
12 | /data/temp/uploadfs
13 | /modules/asset/ui/public/site.js
14 | node_modules
15 | # This folder is created on the fly and contains symlinks updated at startup (we'll come up with a Windows solution that actually copies things)
16 | /public/modules
17 | # We don't commit CSS, only LESS
18 | /public/css/*.css
19 | /public/css/*.map
20 | # Don't commit masters generated on the fly at startup, these import all the rest
21 | /public/css/master-*.less
22 | /.jshintrc
23 | /public/js/_site-compiled.js
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apostrophe 3 headless demo
2 |
3 | ## Get started
4 |
5 | 1. Install dependencies: `npm install`
6 | 2. At the moment, you must have a local copy of `apostrophe` using the `3.0` branch and link that to this project. In whatever local directory you keep your dev work in, run:
7 | 1. `git clone git@github.com:apostrophecms/apostrophe.git && cd apostrophe`
8 | 2. `git fetch && git checkout 3.0` to get on the correct branch.
9 | 3. `npm link` to set Apostrophe up for linking in the project.
10 | 3. Back in the `a3-demo` project, link up Apostrophe: `npm link apostrophe`.
11 |
12 | ## Running the project
13 |
14 | Run `npm run dev` to build the Apostrophe UI and start the site up. Remember, this is during alpha development, so we're all in "dev mode."
15 |
--------------------------------------------------------------------------------
/modules/staff-member/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extend: '@apostrophecms/piece-type',
3 | fields: {
4 | add: {
5 | jobTitle: {
6 | type: 'string',
7 | required: true,
8 | label: 'Job title'
9 | },
10 | photo: {
11 | type: 'area',
12 | label: 'Staff photo',
13 | options: {
14 | max: 1,
15 | widgets: {
16 | '@apostrophecms/image': {}
17 | }
18 | }
19 | },
20 | funFact: {
21 | type: 'string',
22 | label: 'Fun fact'
23 | }
24 | },
25 | group: {
26 | basics: {
27 | label: 'Basics',
28 | fields: [
29 | 'title',
30 | 'visibility',
31 | 'jobTitle',
32 | 'photo',
33 | 'funFact'
34 | ]
35 | }
36 | }
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/local.example.js:
--------------------------------------------------------------------------------
1 | // Settings specific to this server. Change the URL
2 | // if you are deploying in production. Then copy to
3 | // data/local.js. That folder is shared by all
4 | // deployments in our stagecoach recipe
5 |
6 | module.exports = {
7 | modules: {
8 | '@apostrophecms/assets': {
9 | // Set to true for full CSS and JS minify, on staging and production servers
10 | // minify: true
11 | },
12 | // If these are your db settings then you don't need to be explicit. If not
13 | // you can uncomment this and get more specific.
14 | '@apostrophecms/db': {
15 | // uri: 'mongodb://localhost:27017/@apostrophecms/sandbox'
16 | // There is legacy support for host, port, name, user and password options,
17 | // but this is not necessary. They can all go in the uri option like this:
18 | // mongodb://user:password@host:port/dbname
19 | }
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/lib/area.js:
--------------------------------------------------------------------------------
1 | const basicConfig = {
2 | '@apostrophecms/image': {},
3 | '@apostrophecms/rich-text': {
4 | toolbar: [
5 | 'styles',
6 | 'bold',
7 | 'italic',
8 | 'strike',
9 | 'link',
10 | 'bullet_list',
11 | 'ordered_list',
12 | 'blockquote'
13 | ],
14 | styles: [
15 | // you may also use a `class` property with these
16 | {
17 | tag: 'p',
18 | label: 'Paragraph (P)'
19 | },
20 | {
21 | tag: 'h2',
22 | label: 'Heading 2 (H2)'
23 | },
24 | {
25 | tag: 'h3',
26 | label: 'Heading 3 (H3)'
27 | },
28 | {
29 | tag: 'h4',
30 | label: 'Heading 4 (H4)'
31 | }
32 | ]
33 | }
34 | };
35 |
36 | const fullConfig = Object.assign({
37 | 'two-column': {},
38 | article: {}
39 | }, basicConfig);
40 |
41 | module.exports = {
42 | basicConfig,
43 | fullConfig
44 | };
45 |
--------------------------------------------------------------------------------
/deployment/stop:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Shut the site down, for instance by tweaking a .htaccess file to display
4 | # a 'please wait' notice, or stopping a node server
5 |
6 | export NODE_ENV=production
7 |
8 | if [ ! -f "app.js" ]; then
9 | echo "I don't see app.js in the current directory."
10 | exit 1
11 | fi
12 |
13 | # Stop the node app via 'forever'. You'll get a harmless warning if the app
14 | # was not already running. Use `pwd` to make sure we have a full path,
15 | # forever is otherwise easily confused and will stop every server with
16 | # the same filename
17 | forever stop `pwd`/app.js && echo "Site stopped"
18 |
19 | # Stop the app without 'forever'. We recommend using 'forever' for node apps,
20 | # but this may be your best bet for non-node apps
21 | #
22 | # if [ -f "data/pid" ]; then
23 | # kill `cat data/pid`
24 | # rm data/pid
25 | # echo "Site stopped"
26 | # else
27 | # echo "Site was not running"
28 | # fi
29 |
30 |
--------------------------------------------------------------------------------
/deployment/settings:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Settings shared by all targets (staging, production, etc). Usually the
4 | # shortname of the project (which is also the hostname for the frontend
5 | # proxy server used for staging sites) and the directory name. For our
6 | # web apps that use sc-proxy we make sure each is a subdirectory
7 | # of /opt/stagecoach/apps
8 |
9 | # Should match the repo name = short name = everything name!
10 | PROJECT=a3-demo
11 |
12 | DIR=/opt/stagecoach/apps/$PROJECT
13 |
14 | # Adjust the PATH environment variable on the remote host. Here's an example
15 | # for deploying to MacPorts
16 | #ADJUST_PATH='export PATH=/opt/local/bin:$PATH'
17 |
18 | # ... But you probably won't need to on real servers. I just find it handy for
19 | # testing parts of stagecoach locally on a Mac. : is an acceptable "no-op" (do-nothing) statement
20 | ADJUST_PATH=':'
21 |
22 | # ssh port. Sensible people leave this set to 22 but it's common to do the
23 | # "security by obscurity" thing alas
24 | SSH_PORT=22
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 P'unk Avenue LLC
2 |
3 | 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:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | 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.
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "a3-headless-demo",
3 | "version": "1.0.0-beta",
4 | "description": "Apostrophe 3 headless demo site",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "node app",
8 | "build": "node app @apostrophecms/asset:build",
9 | "dev": "nodemon --delay 1000ms -x \"nodemon app.js\""
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": ""
14 | },
15 | "dependencies": {
16 | "@babel/core": "^7.12.10",
17 | "@babel/preset-env": "^7.12.11",
18 | "apostrophe": "^3.1.0"
19 | },
20 | "author": "Apostrophe Technologies, Inc",
21 | "license": "MIT",
22 | "nodemonConfig": {
23 | "delay": 1000,
24 | "verbose": true,
25 | "watch": [
26 | "./app.js",
27 | "./modules/**/*",
28 | "./lib/**/*.js",
29 | "./views/**/*.html"
30 | ],
31 | "ignoreRoot": [
32 | ".git"
33 | ],
34 | "ignore": [
35 | "locales/*.json",
36 | "public/uploads",
37 | "public/apos-frontend/*.js",
38 | "data"
39 | ],
40 | "ext": "json, js, html, scss, vue"
41 | },
42 | "devDependencies": {
43 | "eslint": "^7.8.0",
44 | "eslint-config-apostrophe": "^3.4.0",
45 | "eslint-plugin-node": "^11.1.0",
46 | "nodemon": "^2.0.4"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/scripts/sync-down:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | TARGET="$1"
4 | if [ -z "$TARGET" ]; then
5 | echo "Usage: ./scripts/sync-down production"
6 | echo "(or as appropriate)"
7 | exit 1
8 | fi
9 |
10 | source deployment/settings || exit 1
11 | source "deployment/settings.$TARGET" || exit 1
12 |
13 | #Enter the Mongo DB name (should be same locally and remotely).
14 | dbName=$PROJECT
15 |
16 | #Enter the Project name (should be what you called it for stagecoach).
17 | projectName=$PROJECT
18 |
19 | #Enter the SSH username/url for the remote server.
20 | remoteSSH="-p $SSH_PORT $USER@$SERVER"
21 | rsyncTransport="ssh -p $SSH_PORT"
22 | rsyncDestination="$USER@$SERVER"
23 |
24 | echo "Syncing MongoDB"
25 | ssh $remoteSSH mongodump -d $dbName -o /tmp/mongodump.$dbName &&
26 | rsync -av -e "$rsyncTransport" $rsyncDestination:/tmp/mongodump.$dbName/ /tmp/mongodump.$dbName &&
27 | ssh $remoteSSH rm -rf /tmp/mongodump.$dbName &&
28 | # noIndexRestore increases compatibility between 3.x and 2.x,
29 | # and Apostrophe will recreate the indexes correctly at startup
30 | mongorestore --noIndexRestore --drop -d $dbName /tmp/mongodump.$dbName/$dbName &&
31 | echo "Syncing Files" &&
32 | rsync -av --delete -e "$rsyncTransport" $rsyncDestination:/opt/stagecoach/apps/$projectName/uploads/ ./public/uploads &&
33 | echo "Synced down from $TARGET"
34 | echo "YOU MUST RESTART THE SITE LOCALLY TO REBUILD THE MONGODB INDEXES."
35 |
--------------------------------------------------------------------------------
/modules/program/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extend: '@apostrophecms/piece-type',
3 | fields: {
4 | add: {
5 | description: {
6 | type: 'string',
7 | label: 'Description',
8 | options: {
9 | textarea: true
10 | }
11 | },
12 | startDate: {
13 | type: 'date',
14 | required: true,
15 | label: 'Starting date'
16 | },
17 | endDate: {
18 | type: 'date',
19 | required: true,
20 | label: 'Ending date'
21 | },
22 | cost: {
23 | type: 'float',
24 | required: true,
25 | label: 'Cost (in USD)'
26 | },
27 | ageGroup: {
28 | type: 'select',
29 | required: true,
30 | choices: [
31 | {
32 | label: '6 to 9 year olds',
33 | value: '06to09'
34 | },
35 | {
36 | label: '10 to 12 year olds',
37 | value: '10to12'
38 | },
39 | {
40 | label: '13 to 15 year olds',
41 | value: '13to15'
42 | },
43 | {
44 | label: '16 to 18 year olds',
45 | value: '16to18'
46 | }
47 | ]
48 | }
49 | },
50 | group: {
51 | basics: {
52 | label: 'Basics',
53 | fields: [
54 | 'title',
55 | 'startDate',
56 | 'endDate',
57 | 'ageGroup',
58 | 'description',
59 | 'cost'
60 | ]
61 | }
62 | }
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | require('apostrophe')({
2 | shortName: 'a3-for-gatsby',
3 | baseUrl: 'http://localhost:3000',
4 | // See lib/modules for basic project-level configuration of our modules
5 | // responsible for serving static assets, managing page templates and
6 | // configuring user accounts.
7 |
8 | modules: {
9 | // Apostrophe module configuration
10 |
11 | // Note: most configuration occurs in the respective
12 | // modules' directories. See lib/@apostrophecms/assets/index.js for an example.
13 |
14 | // However any modules that are not present by default in Apostrophe must at
15 | // least have a minimal configuration here to turn them on: `moduleName: {}`
16 |
17 | // Custom CSS classes for standard apostrophe widgets
18 | '@apostrophecms/rich-text-widget': {
19 | options: {
20 | className: 'rl-rte mb-4'
21 | }
22 | },
23 | '@apostrophecms/image-widget': {
24 | options: {
25 | className: 'rl-image mb-4'
26 | }
27 | },
28 | '@apostrophecms/video-widget': {
29 | options: {
30 | className: 'rl-video mb-4'
31 | }
32 | },
33 | // Manages apostrophe's overall asset pipeline
34 | '@apostrophecms/asset': {
35 | // When not in production, refresh the page on restart
36 | options: {
37 | refreshOnRestart: true
38 | }
39 | },
40 |
41 | // A home for our own project-specific javascript and SASS assets
42 | asset: {},
43 |
44 | // A custom widget with two columns
45 | 'two-column-widget': {},
46 |
47 | // A page type for ordinary pages
48 | 'default-page': {},
49 |
50 | // A piece type for camp programs
51 | program: {},
52 | // A piece type for camp staff
53 | 'staff-member': {}
54 | }
55 | });
56 |
--------------------------------------------------------------------------------
/scripts/sync-up:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TARGET="$1"
4 | if [ -z "$TARGET" ]; then
5 | echo "Usage: ./scripts/sync-up production"
6 | echo "(or as appropriate)"
7 | echo
8 | echo "THIS WILL CLOBBER EVERYTHING ON THE"
9 | echo "TARGET SITE. MAKE SURE THAT IS WHAT"
10 | echo "YOU WANT!"
11 | exit 1
12 | fi
13 |
14 | read -p "THIS WILL CRUSH THE SITE'S CONTENT ON $TARGET. Are you sure? " -n 1 -r
15 | echo
16 | if [[ ! $REPLY =~ ^[Yy]$ ]]
17 | then
18 | exit 1
19 | fi
20 |
21 | source deployment/settings || exit 1
22 | source "deployment/settings.$TARGET" || exit 1
23 |
24 | #Enter the Mongo DB name (should be same locally and remotely).
25 | dbName=$PROJECT
26 |
27 | #Enter the Project name (should be what you called it for stagecoach).
28 | projectName=$PROJECT
29 |
30 | #Enter the SSH username/url for the remote server.
31 | remoteSSH="-p $SSH_PORT $USER@$SERVER"
32 | rsyncTransport="ssh -p $SSH_PORT"
33 | rsyncDestination="$USER@$SERVER"
34 |
35 | echo "Syncing MongoDB"
36 | mongodump -d $dbName -o /tmp/mongodump.$dbName &&
37 | echo rsync -av -e "$rsyncTransport" /tmp/mongodump.$dbName/ $rsyncDestination:/tmp/mongodump.$dbName &&
38 | rsync -av -e "$rsyncTransport" /tmp/mongodump.$dbName/ $rsyncDestination:/tmp/mongodump.$dbName &&
39 | rm -rf /tmp/mongodump.$dbName &&
40 | # noIndexRestore increases compatibility between 3.x and 2.x,
41 | # and Apostrophe will recreate the indexes correctly at startup
42 | ssh $remoteSSH mongorestore --noIndexRestore --drop -d $dbName /tmp/mongodump.$dbName/$dbName &&
43 | echo "Syncing Files" &&
44 | rsync -av --delete -e "$rsyncTransport" ./public/uploads/ $rsyncDestination:/opt/stagecoach/apps/$projectName/uploads &&
45 | echo "Synced up to $TARGET"
46 | echo "YOU MUST RESTART THE SITE ON $TARGET TO REBUILD THE MONGODB INDEXES."
47 |
--------------------------------------------------------------------------------
/deployment/dependencies:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Also a good place to ensure any data folders
4 | # that are *not* supposed to be replaced on every deployment exist
5 | # and create a symlink to them from the latest deployment directory.
6 |
7 | # The real 'data' folder is shared. It lives two levels up and one over
8 | # (we're in a deployment dir, which is a subdir of 'deployments', which
9 | # is a subdir of the project's main dir)
10 |
11 | export NODE_ENV=production
12 |
13 | HERE=`pwd`
14 | mkdir -p ../../data
15 | ln -s ../../data $HERE/data
16 |
17 | # We also have a shared uploads folder which is convenient to keep
18 | # in a separate place so we don't have to have two express.static calls
19 |
20 | mkdir -p ../../uploads
21 | ln -s ../../../uploads $HERE/public/uploads
22 |
23 | # Install any dependencies that can't just be rsynced over with
24 | # the deployment. Example: node apps have npm modules in a
25 | # node_modules folder. These may contain compiled C++ code that
26 | # won't work portably from one server to another.
27 |
28 | # This script runs after the rsync, but before the 'stop' script,
29 | # so your app is not down during the npm installation.
30 |
31 | # Make sure node_modules exists so npm doesn't go searching
32 | # up the filesystem tree
33 | mkdir -p node_modules
34 |
35 | # If there is no package.json file then we don't need npm install
36 | if [ -f './package.json' ]; then
37 | # Install npm modules
38 | # Use a suitable version of Python
39 | # export PYTHON=/usr/bin/python26
40 | npm install
41 | if [ $? -ne 0 ]; then
42 | echo "Error during npm install!"
43 | exit 1
44 | fi
45 | fi
46 |
47 | node app @apostrophecms/migration:migrate
48 | # Generate new static asset files for this
49 | # deployment of the app without shutting down
50 | # (TODO: for 3.0 this is actually disruptive because
51 | # we don't have a generation identifier yet)
52 | npm run build
53 |
--------------------------------------------------------------------------------
/deployment/start:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Make the site live again, for instance by tweaking a .htaccess file
4 | # or starting a node server. In this example we also set up a
5 | # data/port file so that sc-proxy.js can figure out what port
6 | # to forward traffic to for this site. The idea is that every
7 | # folder in /var/webapps represents a separate project with a separate
8 | # node process, each listening on a specific port, and they all
9 | # need traffic forwarded from a reverse proxy server on port 80
10 |
11 | # Useful for debugging
12 | #set -x verbose
13 |
14 | # Express should not reveal information on errors,
15 | # also optimizes Express performance
16 | export NODE_ENV=production
17 |
18 | if [ ! -f "app.js" ]; then
19 | echo "I don't see app.js in the current directory."
20 | exit 1
21 | fi
22 |
23 | # Assign a port number if we don't yet have one
24 |
25 | if [ -f "data/port" ]; then
26 | PORT=`cat data/port`
27 | else
28 | # No port set yet for this site. Scan and sort the existing port numbers if any,
29 | # grab the highest existing one
30 | PORT=`cat ../../../*/data/port 2>/dev/null | sort -n | tail -1`
31 | if [ "$PORT" == "" ]; then
32 | echo "First app ever, assigning port 3000"
33 | PORT=3000
34 | else
35 | # Bash is much nicer than sh! We can do math without tears!
36 | let PORT+=1
37 | fi
38 | echo $PORT > data/port
39 | echo "First startup, chose port $PORT for this site"
40 | fi
41 |
42 | # Run the app via 'forever' so that it restarts automatically if it fails
43 | # Use `pwd` to make sure we have a full path, forever is otherwise easily confused
44 | # and will stop every server with the same filename
45 |
46 | # Use a "for" loop. A classic single-port file will do the
47 | # right thing, but so will a file with multiple port numbers
48 | # for load balancing across multiple cores
49 | for port in $PORT
50 | do
51 | export PORT=$port
52 | forever --minUptime=1000 --spinSleepTime=10000 -o data/console.log -e data/error.log start `pwd`/app.js && echo "Site started"
53 | done
54 |
55 | # Run the app without 'forever'. Record the process id so 'stop' can kill it later.
56 | # We recommend installing 'forever' instead for node apps. For non-node apps this code
57 | # may be helpful
58 | #
59 | # node app.js >> data/console.log 2>&1 &
60 | # PID=$!
61 | # echo $PID > data/pid
62 | #
63 | #echo "Site started"
64 |
--------------------------------------------------------------------------------
/views/layout.html:
--------------------------------------------------------------------------------
1 | {# Automatically extends the right outer layout and also handles AJAX siutations #}
2 | {% extends data.outerLayout %}
3 |
4 | {% set title = data.piece.title or data.page.title %}
5 | {% block title %}
6 | {{ title }}
7 | {% if not title %}
8 | {{ apos.log('Looks like you forgot to override the title block in a template that does not have access to an Apostrophe page or piece.') }}
9 | {% endif %}
10 | {% endblock %}
11 |
12 | {% block extraHead %}
13 | {#
14 | This block outputs its contents in the HTML document's .
15 | It is a good place to put extra