├── .nvmrc ├── themes └── meteor │ ├── _config.yaml │ ├── source │ ├── style │ │ ├── _global │ │ │ ├── panel.less │ │ │ ├── Radio.less │ │ │ ├── mobile.less │ │ │ ├── Textarea.less │ │ │ ├── Checkbox.less │ │ │ ├── link.less │ │ │ ├── base.less │ │ │ ├── syntax.less │ │ │ ├── animation.less │ │ │ ├── nav.less │ │ │ ├── form.less │ │ │ ├── Input.less │ │ │ ├── Select.less │ │ │ ├── formatting.less │ │ │ └── icon.less │ │ ├── _util │ │ │ ├── easing.import.less │ │ │ ├── link.import.less │ │ │ ├── clearfix.import.less │ │ │ ├── helper.import.less │ │ │ ├── index.import.less │ │ │ ├── text.import.less │ │ │ ├── scrollbar.import.less │ │ │ ├── color.import.less │ │ │ ├── ui.import.less │ │ │ └── typography.import.less │ │ ├── _theme │ │ │ ├── panel.less │ │ │ ├── nav.less │ │ │ ├── sidebar.less │ │ │ ├── layout.less │ │ │ └── content.less │ │ └── style.less │ ├── images │ │ ├── logo.png │ │ ├── OSXsmall.png │ │ ├── favicon.png │ │ ├── tuxSmall.png │ │ ├── windowsSmall.png │ │ ├── icon-white.svg │ │ └── logo-coralspace-left.svg │ ├── fonts │ │ ├── percolate.eot │ │ ├── percolate.ttf │ │ └── percolate.woff │ └── script │ │ ├── smooth-scroll.min.js │ │ └── main.js │ └── layout │ ├── partials │ ├── illustration-help.ejs │ ├── illustration-logs.ejs │ ├── illustration-compass.ejs │ ├── illustration-support.ejs │ ├── sidebar.ejs │ ├── illustration-guide.ejs │ └── illustration-github.ejs │ ├── page.ejs │ └── layout.ejs ├── .gitignore ├── assets ├── theme-colors.less └── api-box.html ├── README.md ├── scripts ├── parseTagOptions.js └── dl.js ├── circle.yml ├── package.json ├── source ├── chapters │ ├── 1 │ │ ├── conclusion.md │ │ ├── reactivity.md │ │ ├── methods.md │ │ ├── security.md │ │ ├── pubsub.md │ │ ├── collections.md │ │ ├── users.md │ │ ├── intro.md │ │ └── meteorSnacks.md │ ├── 2 │ │ ├── conclusion.md │ │ ├── intro.md │ │ ├── react.md │ │ └── css.md │ └── 3 │ │ ├── conclusion.md │ │ ├── fixtures.md │ │ ├── publications.md │ │ ├── testing.md │ │ ├── reusable-modules.md │ │ ├── static-type-checking.md │ │ ├── linting.md │ │ ├── emails.md │ │ ├── structure.md │ │ ├── microservices.md │ │ └── methods.md └── index.md ├── Contributing.md └── _config.yml /.nvmrc: -------------------------------------------------------------------------------- 1 | v8.16.1 2 | -------------------------------------------------------------------------------- /themes/meteor/_config.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/panel.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | npm-debug.log 4 | deploy.sh 5 | /public 6 | db.json -------------------------------------------------------------------------------- /assets/theme-colors.less: -------------------------------------------------------------------------------- 1 | // Haven't made any changes as we want the default Meteor colors 2 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/easing.import.less: -------------------------------------------------------------------------------- 1 | @easing: cubic-bezier(0.175, 0.885, 0.335, 1.05); 2 | -------------------------------------------------------------------------------- /themes/meteor/source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/images/logo.png -------------------------------------------------------------------------------- /themes/meteor/source/fonts/percolate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/fonts/percolate.eot -------------------------------------------------------------------------------- /themes/meteor/source/fonts/percolate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/fonts/percolate.ttf -------------------------------------------------------------------------------- /themes/meteor/source/images/OSXsmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/images/OSXsmall.png -------------------------------------------------------------------------------- /themes/meteor/source/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/images/favicon.png -------------------------------------------------------------------------------- /themes/meteor/source/images/tuxSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/images/tuxSmall.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Meteor Tuts - http://www.meteor-tuts.com 2 | 3 | This package has been cloned from: 4 | https://github.com/meteor/docs 5 | 6 | 7 | -------------------------------------------------------------------------------- /themes/meteor/source/fonts/percolate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/fonts/percolate.woff -------------------------------------------------------------------------------- /themes/meteor/source/images/windowsSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cult-of-coders/meteor-tuts/HEAD/themes/meteor/source/images/windowsSmall.png -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/link.import.less: -------------------------------------------------------------------------------- 1 | .link(@color) { 2 | color: @color; 3 | &:link, 4 | &:visited { color: @color; } 5 | &:active { color: darken(@color, 5%); } 6 | } 7 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/Radio.less: -------------------------------------------------------------------------------- 1 | @import "../_util/index.import.less"; 2 | @import "Checkbox.less"; 3 | 4 | label.radio { 5 | &:extend(label.checkbox all); 6 | 7 | input[type="radio"] + span:before, 8 | input[type="radio"] + span:after { border-radius: 1em; } 9 | } 10 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/clearfix.import.less: -------------------------------------------------------------------------------- 1 | // Modern Clearfix 2 | // Modified from http://nicolasgallagher.com/micro-clearfix-hack/ 3 | .clearfix() { 4 | *zoom: 1; 5 | 6 | &:after { 7 | clear: both; 8 | content: " "; /* 1 */ 9 | display: table; /* 2 */ 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/helper.import.less: -------------------------------------------------------------------------------- 1 | .position(@type; @top: auto; @right: auto; @bottom: auto; @left: auto; @width: auto; @height: auto) { 2 | position: @type; 3 | top: @top; 4 | right: @right; 5 | bottom: @bottom; 6 | left: @left; 7 | width: @width; 8 | height: @height; 9 | } 10 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/mobile.less: -------------------------------------------------------------------------------- 1 | // Show only on desktop 2 | .show-mobile { 3 | @media screen and (min-width: @breakpoint) { 4 | display: none !important; 5 | } 6 | } 7 | 8 | 9 | // Show only on desktop 10 | .show-desktop { 11 | @media screen and (max-width: (@breakpoint - 1px)) { 12 | display: none !important; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /scripts/parseTagOptions.js: -------------------------------------------------------------------------------- 1 | // sort of hacky but allows x:y 2 | module.exports = function(args) { 3 | if (args.length === 0) { 4 | return {}; 5 | } 6 | var argsJson = '{"' + args.join('","').replace(/:/g, '":"') + '"}'; 7 | try { 8 | return JSON.parse(argsJson); 9 | } catch (e) { 10 | console.error(args, argsJson); 11 | throw new Error("Couldn't parse arguments"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/index.import.less: -------------------------------------------------------------------------------- 1 | // Normalize.import.less is imported separately 2 | 3 | @import 'clearfix.import.less'; 4 | @import 'color.import.less'; 5 | @import 'easing.import.less'; 6 | @import 'helper.import.less'; 7 | @import 'lesshat.import.less'; 8 | @import 'link.import.less'; 9 | @import 'scrollbar.import.less'; 10 | @import 'text.import.less'; 11 | @import 'typography.import.less'; 12 | @import 'ui.import.less'; 13 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 0.12 4 | 5 | checkout: 6 | post: 7 | - git submodule update --init 8 | 9 | dependencies: 10 | cache_directories: 11 | - "node_modules" 12 | override: 13 | - npm install -g hexo-cli 14 | - npm install 15 | 16 | test: 17 | override: 18 | # maybe we will need tests in the future 19 | - echo 'ok!' 20 | 21 | deployment: 22 | s3: 23 | branch: /^(master|version-.*)/ 24 | commands: 25 | - npm run deploy 26 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/text.import.less: -------------------------------------------------------------------------------- 1 | .subheading-caps() { 2 | .type-bold; 3 | letter-spacing: .35em; 4 | text-transform: uppercase; 5 | } 6 | 7 | .subheading-caps(center) { 8 | .subheading-caps(); 9 | text-indent: .35em; 10 | } 11 | 12 | .ellipsized() { 13 | overflow: hidden; 14 | text-overflow: ellipsis; 15 | white-space: nowrap; 16 | } 17 | 18 | .force-wrap() { 19 | word-wrap: break-word; 20 | word-break: break-all; 21 | -ms-word-break: break-all; 22 | word-break: break-word; 23 | 24 | .hyphens(auto); 25 | } 26 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_theme/panel.less: -------------------------------------------------------------------------------- 1 | .panel { 2 | @media screen and (min-width: @breakpoint) { display: none; } 3 | 4 | .panel-item { 5 | .std-xpadding; 6 | .font-s2; 7 | .type-semibold; 8 | display: block; 9 | padding-top: .5rem; 10 | padding-bottom: .5rem; 11 | position: relative; 12 | 13 | &.active, 14 | &:hover { 15 | background: @color-primary; 16 | 17 | a { .link(@color-lightest); } 18 | 19 | &:before { 20 | .transform(scale3d(1,1,1)); 21 | background: @color-primary; 22 | } 23 | } 24 | 25 | a { 26 | .link(@color-dark); 27 | .type-semibold; 28 | display: block; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scripts/dl.js: -------------------------------------------------------------------------------- 1 | /* global hexo */ 2 | 3 | var parseTagOptions = require('./parseTagOptions'); 4 | 5 | hexo.extend.tag.register('dtdd', function(args, content) { 6 | var options = parseTagOptions(args); 7 | 8 | var typespan = ''; 9 | if (options.type) { 10 | typespan = '' + options.type + ''; 11 | } 12 | 13 | var idstr = ''; 14 | if (options.id) { 15 | idstr = 'id="' + options.id + '"'; 16 | } 17 | var namespan = '' + options.name + ''; 18 | 19 | return hexo.render.render({text: content, engine: 'md'}) 20 | .then(function(markdownContent) { 21 | return '
' + namespan + typespan + '
' + markdownContent + '
'; 22 | }); 23 | }, { ends: true, async: true }); 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexo-site", 3 | "version": "0.0.0", 4 | "private": true, 5 | "hexo": { 6 | "version": "3.9.0" 7 | }, 8 | "dependencies": { 9 | "canonical-json": "0.0.4", 10 | "handlebars": "^4.4.3", 11 | "hexo": "^3.9.0", 12 | "hexo-generator-archive": "^0.1.5", 13 | "hexo-generator-category": "^0.1.2", 14 | "hexo-generator-index": "^0.1.2", 15 | "hexo-generator-sitemap": "^1.2.0", 16 | "hexo-generator-tag": "^0.1.1", 17 | "hexo-renderer-ejs": "^0.1.0", 18 | "hexo-renderer-less": "^0.1.3", 19 | "hexo-renderer-marked": "^0.2.4", 20 | "hexo-renderer-stylus": "^0.3.0", 21 | "hexo-server": "^0.2.0", 22 | "jsdoc": "git+https://github.com/meteor/jsdoc.git#espree-3.1", 23 | "showdown": "^1.9.0", 24 | "underscore": "^1.9.1" 25 | }, 26 | "scripts": { 27 | "build": "hexo generate", 28 | "start": "hexo server" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/chapters/2/conclusion.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Chapter 2 - Conclusion' 3 | description: Conclusion 4 | disqusPage: 'Chapter 2: Conclusion' 5 | --- 6 | 7 | Good job on making it through Chapter 2! 8 | 9 | You learned how to integrate the View Layer into Meteor. 10 | What's next ? 11 | Well, you need to do your homework first, because it will help you form 12 | new neural synapses that will enable you to remember the underlying mechanism and code faster. 13 | 14 | The next chapter will show you how all the knowledge from Chapter 1 & Chapter 2 can be used in complex projects: 15 | Healthcare applications, Government applications, Multi-tenant applications, Role-Based Access Control, CRMs, 16 | which are the usual enterprise type of applications that may require a bigger team to develop, 17 | and a lot of coding. 18 | 19 | We'll understand how to keep it under-control, how to use testing and how 20 | to continuously integrate and of course: how to deploy! 21 | 22 | It is going to be awesome! 23 | 24 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/scrollbar.import.less: -------------------------------------------------------------------------------- 1 | /// Mixin to customize scrollbars 2 | /// Beware, this does not work in all browsers 3 | /// @author Hugo Giraudel 4 | /// @param {Length} $size - Horizontal scrollbar's height and vertical scrollbar's width 5 | /// @param {Color} $foreground-color - Scrollbar's color 6 | /// @param {Color} $background-color [mix($foreground-color, white, 50%)] - Scrollbar's color 7 | /// @example scss - Scrollbar styling 8 | /// @include scrollbars(.5em, slategray); 9 | .scrollbars(@size, @foreground-color, @background-color) { 10 | // For Google Chrome 11 | &::-webkit-scrollbar { 12 | width: @size; 13 | height: @size; 14 | } 15 | 16 | &::-webkit-scrollbar-thumb { 17 | background: @foreground-color; 18 | border-radius: 1em; 19 | cursor: grab; 20 | 21 | } 22 | 23 | &::-webkit-scrollbar-track { 24 | background: @background-color; 25 | } 26 | 27 | // For Internet Explorer 28 | body { 29 | scrollbar-face-color: @foreground-color; 30 | scrollbar-track-color: @background-color; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/color.import.less: -------------------------------------------------------------------------------- 1 | // Primary 2 | @color-primary: #ff9c00;// coral 3 | @color-secondary: #56579B;// violet 4 | @color-tertiary: #BEA76E;// gold 5 | @color-complementary: #5FD500; // sea green 6 | @color-ancillary: #0F2A4A;// midnight blue 7 | 8 | // Monochrome 9 | @color-lightest: #fff; 10 | @color-lighter: #f8f8f8; 11 | @color-light: #f3f3f3; 12 | @color-mediumlight: #EEE; 13 | @color-medium: #CCC; 14 | @color-mediumdark: #999; 15 | @color-dark: #666; 16 | @color-darker: #444; 17 | @color-darkest: #333; 18 | 19 | // Accent 20 | @color-accent-coolest: #E2DFF3; // baby purple 21 | @color-accent-cooler: #DFECF2; // baby blue 22 | @color-accent-cool: #DEF2E9; // baby teal 23 | @color-accent-warm: #E5F2DE; // baby green 24 | @color-accent-warmer: #F2EFDE; // baby yellow 25 | @color-accent-warmest: #F2DFDF; // baby peach 26 | 27 | // Validation 28 | @color-positive: #63C131; // green 29 | @color-negative: #ff4800; // 30 | @color-neutral: #ffffe4; 31 | 32 | // Third-party 33 | @color-facebook: #3b5998; 34 | @color-google: #58586d; 35 | @color-twitter: #46c8f5; 36 | -------------------------------------------------------------------------------- /themes/meteor/source/style/style.less: -------------------------------------------------------------------------------- 1 | @import './_util/normalize.import.less'; 2 | 3 | // Mixins & Utilities 4 | @import './_util/index.import.less'; 5 | 6 | // Overrides specified by the user 7 | @import '../../../../assets/theme-colors.less'; 8 | 9 | // global namespace 10 | @import './_global/animation.less'; 11 | @import './_global/base.less'; 12 | @import './_global/button.less'; 13 | @import './_global/docsearch.less'; 14 | @import './_global/formatting.less'; 15 | @import './_global/Textarea.less'; 16 | @import './_global/form.less'; 17 | @import './_global/Input.less'; 18 | @import './_global/Radio.less'; 19 | @import './_global/Checkbox.less'; 20 | @import './_global/Select.less'; 21 | @import './_global/icon.less'; 22 | @import './_global/link.less'; 23 | @import './_global/mobile.less'; 24 | @import './_global/nav.less'; 25 | @import './_global/panel.less'; 26 | @import './_global/syntax.less'; 27 | 28 | 29 | // global templates 30 | @import './_theme/layout.less'; 31 | @import './_theme/panel.less'; 32 | @import './_theme/sidebar.less'; 33 | @import './_theme/content.less'; 34 | @import './_theme/nav.less'; 35 | -------------------------------------------------------------------------------- /themes/meteor/source/images/icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/Textarea.less: -------------------------------------------------------------------------------- 1 | @import "../_util/index.import.less"; 2 | 3 | // Input's look like text fields 4 | textarea { 5 | .font-s2; 6 | .placeholder(@color-mediumdark); 7 | 8 | padding: .7111em 1em; //40 9 | 10 | background: @color-lightest; 11 | border:none; 12 | box-sizing: border-box; 13 | border-radius: 0; 14 | color: @color-darkest; 15 | display: block; 16 | outline: none; 17 | width: 100%; 18 | -webkit-appearance: none; 19 | 20 | &[disabled] { opacity: .5; } 21 | 22 | &.small { 23 | font-size: 13px; 24 | line-height: 18px; 25 | padding: .38em 1em; //40 26 | } 27 | 28 | &.alert { box-shadow: @color-negative 0 0 1px 0 inset; } 29 | 30 | &.inverse { 31 | .placeholder(@color-medium); 32 | background-color: @color-darkest; 33 | color: @color-lightest; 34 | } 35 | 36 | // a form input with no chrome at all (ie. appears just as text) 37 | &.nochrome { 38 | padding: 0; 39 | 40 | border: none; 41 | box-shadow: none; 42 | background: none; 43 | 44 | &:focus, 45 | &:active, 46 | &:hover {} 47 | } 48 | } 49 | 50 | textarea.secondary { 51 | box-shadow: @color-mediumlight 0 0 0 1px inset; 52 | } 53 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/Checkbox.less: -------------------------------------------------------------------------------- 1 | @import "../_util/index.import.less"; 2 | 3 | label.checkbox { 4 | min-height: 1em; 5 | position: relative; 6 | 7 | cursor: pointer; 8 | 9 | input { 10 | .font-s2; 11 | margin: 0 .7em 0 0; 12 | visibility: hidden; 13 | 14 | & + span { 15 | display: inline-block; 16 | vertical-align: top; 17 | line-height: 1; 18 | 19 | &:before, 20 | &:after { 21 | .position(absolute, 0, auto, auto, 0, 14px, 14px); 22 | content: ''; 23 | display: block; 24 | } 25 | } 26 | 27 | 28 | & + span:before { box-shadow: @color-mediumdark 0 0 0 1px inset; } 29 | 30 | &:checked + span:before { box-shadow: @color-complementary 0 0 0 1px inset; } 31 | 32 | & + span:after { 33 | .transition(all 150ms ease-out); 34 | .transform(scale3d(0,0,1)); 35 | 36 | //overrides 37 | height: 10px; 38 | margin-left: 2px; 39 | margin-top: 2px; 40 | width: 10px; 41 | 42 | opacity: 0; 43 | } 44 | 45 | &:checked + span:after { 46 | .transform(scale3d(1,1,1)); 47 | background: @color-complementary; 48 | opacity: 1; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /source/chapters/1/conclusion.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conclusions 3 | description: Here we are, at the end of the first chapter. 4 | disqusPage: 'Chapter 1: Conclusion' 5 | --- 6 | 7 | Even if this is the beginning of the 1st chapter, we just scratched the surface. Meteor has so many good things to offer! 8 | We are certain you have fallen in love with this framework, and we look forward to help you on this new journey! 9 | 10 | You now have the knowledge how to use Meteor's powers in your applications! You've learned how to: 11 | - store data in a database via Collections 12 | - use methods to perform server-side actions and return responses to the client 13 | - use Meteor's reactive system to develop live updates systems in your applications 14 | - secure your methods/publications in order to develop robust applications 15 | 16 | If you're like us, you will want to know more and more! Here's what we recommend: 17 | - https://guide.meteor.com/ 18 | - https://themeteorchef.com/ 19 | 20 | Also, we do this tutorial out of passion, and we'd like your support! 21 | Feedback is a critical component of any development system. Because of this, we encourage you to interact with us and help us make meteor-tuts better! 22 | Share your experience us regarding the content in this tutorial and help us improve it for other developers! 23 | -------------------------------------------------------------------------------- /themes/meteor/layout/partials/illustration-help.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/ui.import.less: -------------------------------------------------------------------------------- 1 | @breakpoint: 600px; 2 | @page-margin: 5.55555%; 3 | 4 | 5 | .page-margins() { 6 | @media screen and (min-width: (@breakpoint * 1)) { margin: 0 1*@page-margin; } 7 | @media screen and (min-width: (@breakpoint * 1.5)) { margin: 0 1.5*@page-margin; } 8 | @media screen and (min-width: (@breakpoint * 2)) { margin: 0 2*@page-margin; } 9 | } 10 | 11 | .std-ypadding() { 12 | padding-top: 1.25rem; //20px 13 | padding-bottom: 1.25rem; 14 | 15 | @media screen and (min-width: @breakpoint) { 16 | padding-top: 1.875rem; //30px 17 | padding-bottom: 1.875rem; 18 | } 19 | } 20 | 21 | .std-xpadding() { 22 | padding-left: 1.25rem; //20px 23 | padding-right: 1.25rem; 24 | 25 | @media screen and (min-width: @breakpoint) { 26 | padding-left: 1.875rem; //30 27 | padding-right: 1.875rem; 28 | } 29 | } 30 | 31 | .inline-block-whitespace() { 32 | // Removes whitespace from display:inline-block layouts 33 | // Sets font-size to 0 to remove whitespace and resets font-size for child elements 34 | // Used primarily in grids 35 | 36 | font-size: 0; 37 | > * { .font-s3; } 38 | } 39 | 40 | .term-code() { 41 | .type-code; 42 | .font-code; 43 | color: @color-complementary; 44 | 45 | .type { 46 | .font-s1; 47 | .type-primary; 48 | .type-italic; 49 | color: @color-dark; 50 | margin-left: 10px; 51 | } 52 | 53 | a { &:extend(.link.primary); } 54 | } -------------------------------------------------------------------------------- /themes/meteor/layout/partials/illustration-logs.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/meteor/layout/partials/illustration-compass.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/link.less: -------------------------------------------------------------------------------- 1 | @import "../_util/index.import.less"; 2 | 3 | a, 4 | .link { 5 | .transition( all 250ms ease-out ); 6 | .type-bold; 7 | cursor: pointer; 8 | text-decoration: none; 9 | 10 | &:visited { color: @color-darkest; } 11 | } 12 | 13 | 14 | .link { 15 | &:hover { text-decoration: underline; } 16 | &:focus { outline: none; } //hides outline in FF 17 | &:visited { color: inherit; } 18 | 19 | &.primary { .link(@color-primary); } 20 | &.secondary { .link(@color-secondary); } 21 | &.tertiary { .link(@color-dark); } 22 | &.complementary { .link(@color-complementary); } 23 | 24 | // When a file uploading is dressed as a link 25 | &.upload { 26 | display: inline-block; 27 | overflow: hidden; 28 | position: relative; 29 | vertical-align: bottom; 30 | 31 | input[type="file"] { 32 | .position(absolute, 0,0,0,0); 33 | opacity: 0; 34 | } 35 | } 36 | 37 | //When a link is on a dark background 38 | &.inverse { 39 | color: @color-lightest; 40 | &:link, 41 | &:visited { color: @color-lightest; } 42 | &:hover { color: @color-light; } 43 | &:active { color: @color-medium; } 44 | } 45 | 46 | &.inverse-alt { 47 | color: fade(@color-lightest, 70%); 48 | &:link, 49 | &:visited { color: fade(@color-lightest, 70%); } 50 | &:hover { color: fade(@color-lightest, 100%); } 51 | &:active { color: @color-medium; } 52 | } 53 | 54 | > [class*="icon-"] { 55 | font-size: 90%; 56 | display: inline-block; 57 | margin-right: .25em; 58 | vertical-align: baseline; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/base.less: -------------------------------------------------------------------------------- 1 | // the idea is to put base styles in here 2 | * { 3 | .box-sizing(border-box); 4 | -webkit-tap-highlight-color:rgba(0,0,0,0); 5 | -webkit-tap-highlight-color: transparent; /* For some Androids */ 6 | } 7 | 8 | html, button, input, textarea, select { 9 | .type-primary; 10 | outline: none; 11 | -webkit-font-smoothing: antialiased; 12 | -moz-osx-font-smoothing: grayscale; 13 | } 14 | 15 | body { 16 | .type-primary; 17 | .font-s3(); 18 | color: @color-darkest; 19 | background-color: @color-ancillary; 20 | -webkit-overflow-scrolling: touch; 21 | overflow-y: scroll; 22 | } 23 | 24 | /* Default type layout */ 25 | h1, h2, h3, h4, h5, h6 { 26 | .type-normal; 27 | margin: 0; 28 | padding: 0; 29 | } 30 | 31 | h1 { .font-m3; } 32 | h2 { .font-m2; } 33 | h3 { .font-m1; } 34 | h4 { .font-s3; } 35 | h5 {} 36 | h6 {} 37 | 38 | p {} 39 | 40 | sub, 41 | sup { font-size: .8em; } 42 | 43 | sub { bottom: -.2em; } 44 | 45 | sup { top: -.2em; } 46 | 47 | b { .type-bold; } 48 | 49 | em { 50 | .type-semibold; 51 | font-style: normal; 52 | } 53 | 54 | hr { 55 | border: none; 56 | border-top: 1px solid @color-mediumlight; 57 | clear: both; 58 | margin-bottom: 1.25rem; 59 | } 60 | 61 | code, 62 | pre { 63 | .type-code; 64 | .font-code; 65 | } 66 | 67 | code { 68 | display: inline-block; 69 | padding-left: 2px; 70 | padding-right: 2px; 71 | vertical-align: baseline; 72 | 73 | color: darken(@color-complementary, 7%); 74 | } 75 | 76 | pre { 77 | padding: 1em 1.25em; 78 | white-space: pre-wrap; 79 | 80 | background: @color-lighter; 81 | color: @color-darkest; 82 | } 83 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_util/typography.import.less: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,300,400italic,600,700); 2 | 3 | .type-primary() { 4 | font-family: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | } 6 | 7 | .type-light() { font-weight: 300; } 8 | .type-normal() { font-weight: 400; } 9 | .type-italic() { font-style: italic; } 10 | .type-semibold() { font-weight: 600; } 11 | .type-bold() { font-weight: 700; } 12 | 13 | .type-code() { 14 | font-family: "Andale Mono WT", "Andale Mono", "Menlo", "Lucida Console", "Lucida Sans Typewriter", Monaco, monospace; 15 | font-weight: 400; 16 | } 17 | 18 | 19 | // X-Large 20 | .font-x1 { 21 | font-size: 56px; 22 | line-height: 1; 23 | } 24 | 25 | // Large 26 | .font-l3() { 27 | font-size: 48px; 28 | line-height: 1; 29 | } 30 | 31 | .font-l2() { 32 | font-size: 40px; 33 | line-height: 1; 34 | } 35 | 36 | .font-l1() { 37 | font-size: 32px; 38 | line-height: 1; 39 | } 40 | 41 | // Medium 42 | .font-m3() { 43 | font-size: 28px; 44 | line-height: 1; 45 | } 46 | 47 | .font-m2() { 48 | font-size: 24px; 49 | line-height: 1; 50 | } 51 | 52 | .font-m1() { 53 | font-size: 20px; 54 | line-height: 1; 55 | } 56 | 57 | // Small 58 | .font-s3() { //this sets the baseline for the layout but gets overridden per template 59 | font-size: 16px; 60 | line-height: 24px; 61 | } 62 | 63 | .font-s2() { 64 | font-size: 14px; 65 | line-height: 20px; 66 | } 67 | 68 | .font-s1() { 69 | font-size: 12px; 70 | line-height: 16px; 71 | } 72 | 73 | .font-code() { 74 | //yields a footprint equivalent to 16px in Source Sans Pro 75 | font-size: 90%; 76 | line-height: 1.5; 77 | } 78 | -------------------------------------------------------------------------------- /themes/meteor/layout/partials/illustration-support.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /source/chapters/3/conclusion.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Chapter 3 - Conclusion' 3 | description: On your way to properly scale 4 | disqusPage: 'Chapter 3: Conclusion' 5 | --- 6 | 7 | ## Thank you! 8 | 9 | We really hope that this chapter has shared some insights into how to architect your Meteor app, and what are some 10 | of the best practices we identified. 11 | 12 | You should be on your way now to write beautiful, decoupled code that is easy to understand. 13 | 14 | Now, I have a task for you, remember that first task the user received in his intro ? 15 | 16 | Let's try and apply the principles we discussed and go ahead and create a public GitHub repository and write a project 17 | that will do the following: 18 | 19 | ## Beat the Boss 20 | 21 | - Use React as the view layer 22 | - Create fixtures for users and admin 23 | - Microservicify admin and app 24 | - Ability to register/login/forgot-password 25 | - Ability to create a post (Ask for title and description) 26 | - Make sure the post has createdAt, updatedAt, createdBy, updatedBy 27 | - Ability to list all approved posts on the route ("/posts") 28 | - Ability to view a single Post 29 | - As an Admin I need the ability to approve a post 30 | - When a new post is created the admins should get notified by email 31 | - Write tests 32 | 33 | Focus on backend, not frontend. The purpose here is to architect the backend right. 34 | 35 | Would you pass the *Bigshot Code Reviewer*'s review? 36 | 37 | Leave your link to the repository down below, and let other users review it! See if it's truly Enterprise level. 38 | 39 | 40 | ## Tell us what you think 41 | 42 | Your feedback is very important. Feel free to ask questions, if they are specific to a certain part of this chapter, 43 | go to that page and leave a comment there. Thank you! -------------------------------------------------------------------------------- /assets/api-box.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{locus}} 5 |
6 | 7 | <{{hTag}} title="{{title}}" class="title-api selflink" id={{id}}> 8 | {{{signature}}} 9 | 10 | 11 |
12 | {{#if importName}} 13 |
import { {{importName}} } from 'meteor/{{module}}'
14 | {{/if}} 15 | 16 | {{#if filepath}} 17 | 18 | ({{filepath}}, line {{lineno}}) 19 | 20 | {{/if}} 21 |
22 |
23 | 24 |
25 |
26 | {{{markdown summary}}} 27 |
28 | 29 | {{#if paramsNoOptions}} 30 |

Arguments

31 |
32 | {{#each paramsNoOptions}} 33 |
34 | {{name}} 35 | {{{typeNames type.names}}} 36 |
37 |
38 | {{{description}}} 39 |
40 | {{/each}} 41 |
42 | {{/if}} 43 | 44 | {{#if options}} 45 |

Options

46 |
47 | {{#each options}} 48 |
49 | {{name}} 50 | {{{typeNames type.names}}} 51 |
52 |
53 | {{{description}}} 54 |
55 | {{/each}} 56 |
57 | {{/if}} 58 | 59 | {{#if UI.contentBlock}} 60 | {{#markdown}}{{> UI.contentBlock}}{{/markdown}} 61 | {{/if}} 62 |
63 |
64 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_global/syntax.less: -------------------------------------------------------------------------------- 1 | // Grabbed from legacy docs theme 2 | .gutter pre { 3 | color: #ddd; 4 | } 5 | 6 | pre { 7 | color: @color-darker; 8 | 9 | .function .keyword, 10 | .constant { 11 | color: #0092db 12 | } 13 | 14 | .keyword, 15 | .attribute { 16 | color: #e96900 17 | } 18 | 19 | .number, 20 | .literal { 21 | color: #AE81FF 22 | } 23 | 24 | .tag, 25 | .tag .title, 26 | .change, 27 | .winutils, 28 | .flow, 29 | .lisp .title, 30 | .clojure .built_in, 31 | .nginx .title, 32 | .tex .special { 33 | color: #2973b7 34 | } 35 | 36 | .class .title { 37 | color: #4077BF 38 | } 39 | 40 | .symbol, 41 | .symbol .string, 42 | .value, 43 | .regexp { 44 | color: #90a959 45 | } 46 | 47 | .title { 48 | color: #A6E22E 49 | } 50 | 51 | .tag .value, 52 | .string, 53 | .subst, 54 | .haskell .type, 55 | .preprocessor, 56 | .ruby .class .parent, 57 | .built_in, 58 | .sql .aggregate, 59 | .django .template_tag, 60 | .django .variable, 61 | .smalltalk .class, 62 | .javadoc, 63 | .django .filter .argument, 64 | .smalltalk .localvars, 65 | .smalltalk .array, 66 | .attr_selector, 67 | .pseudo, 68 | .addition, 69 | .stream, 70 | .envvar, 71 | .apache .tag, 72 | .apache .cbracket, 73 | .tex .command, 74 | .prompt { 75 | color: #90a959 76 | } 77 | 78 | .comment, 79 | .java .annotation, 80 | .python .decorator, 81 | .template_comment, 82 | .pi, 83 | .doctype, 84 | .deletion, 85 | .shebang, 86 | .apache .sqbracket, 87 | .tex .formula { 88 | color: #b3b3b3 89 | } 90 | 91 | .coffeescript .javascript, 92 | .javascript .xml, 93 | .tex .formula, 94 | .xml .javascript, 95 | .xml .vbscript, 96 | .xml .css, 97 | .xml .cdata { 98 | opacity: 0.5 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /themes/meteor/source/style/_theme/nav.less: -------------------------------------------------------------------------------- 1 | .nav { 2 | .background-image(linear-gradient(top, rgba(255,255,255,.96) 0%, rgba(255,255,255,.99) 100%)); 3 | box-shadow: @color-light 0 -1px 0 0 inset; 4 | 5 | .logo { 6 | height: 40px; 7 | margin-top: -2px; 8 | width: auto; 9 | display: block; 10 | 11 | img { 12 | display: inline-block; 13 | height: 100%; 14 | vertical-align: middle; 15 | } 16 | 17 | span { 18 | .type-normal; 19 | display: inline-block; 20 | vertical-align: middle; 21 | margin-left: 4px; 22 | line-height: 1; 23 | } 24 | } 25 | 26 | .nav-search { 27 | .position(absolute, 0,0,0,0); 28 | .transition(all 300ms ease-out); 29 | opacity: 0; 30 | z-index: -1; 31 | 32 | .input-symbol { 33 | .position(absolute, 0,0,1px,0); 34 | background: @color-lightest; 35 | } 36 | 37 | input { 38 | .transition(all 250ms @easing 00ms); 39 | .transform(translate3d(25%,0,0)); 40 | 41 | height: 100%; 42 | padding-left: 2.5em !important; 43 | width: 100%; 44 | 45 | @media screen and (min-width: @breakpoint) { 46 | font-size: 1rem !important; 47 | padding-left: 4em !important; 48 | } 49 | } 50 | 51 | .icon-search { 52 | .transition(all 300ms @easing ); 53 | .transform(translate3d(50%,0,0)); 54 | 55 | @media screen and (min-width: @breakpoint) { 56 | font-size: 1rem; 57 | left: 0; 58 | padding-left: 1.875rem; 59 | } 60 | } 61 | 62 | 63 | .nav-item { 64 | .transition(all 300ms @easing 200ms); 65 | .transform(scale3d(0,0,0)); 66 | 67 | .icon-close { 68 | .link(@color-medium); 69 | 70 | &:hover { color: @color-dark; } 71 | } 72 | } 73 | } 74 | 75 | &.search-visible { 76 | .nav-search { 77 | opacity: 1; 78 | z-index: 1; 79 | } 80 | 81 | input, 82 | .icon-search { 83 | .transform(translate3d(0,0,0)); 84 | } 85 | 86 | .nav-item { .transform(scale3d(1,1,1));} 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /source/chapters/3/fixtures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Fixtures' 3 | description: Generate dummy data. 4 | disqusPage: 'Chapter 3: Fixtures' 5 | --- 6 | 7 | ## Why? 8 | 9 | The reason for writing fixtures is that once you setup your project, you fill it with relevant data, like users of different types and roles, posts, items, comments, whatever. 10 | 11 | This removes the reason of having a shared database, and it makes onboarding new developers so easy. 12 | 13 | ## Structure 14 | 15 | We will store our fixtures inside `/imports/fixtures` because this way you will not forget about them. They are an essential part of development. 16 | 17 | ```js 18 | // file: /imports/fixtures/index.js 19 | import createUsers from './createUsers'; 20 | import createPostsForUsers from './createPostsForUsers'; 21 | 22 | const runFixtures = function () { 23 | const shouldRun = Meteor.users.find().count() == 0; 24 | 25 | if (shouldRun) { 26 | createUsers(); 27 | createPostsForUsers(); 28 | } 29 | } 30 | 31 | if (!Meteor.isDevelopment) { 32 | runFixtures(); 33 | } 34 | ``` 35 | 36 | Keep a configuration so you can use it for load testing later on: 37 | 38 | ```js 39 | // file: /imports/fixtures/config.js 40 | export default { 41 | USERS_COUNT: 10, 42 | POSTS_PER_USER: 2, 43 | } 44 | ``` 45 | 46 | And make sure you use the config in every fixture module you've got! 47 | 48 | If it helps you for generation you can also use: https://github.com/versolearning/meteor-factory/ 49 | 50 | ## Caution 51 | 52 | If you have hooks that send emails or do API calls make sure you disable them when running your fixtures. 53 | 54 | Keep your fixtures in sync with your schemas, so whenever you update it, make sure to update your fixtures as well. 55 | 56 | Always work on adding fixtures as you add different data. 57 | 58 | Keep fixtures small and be careful when nesting them, you don't want to insert 100,000 documents because of a big nested loop. -------------------------------------------------------------------------------- /source/chapters/3/publications.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Publications' 3 | description: How to architect publications 4 | disqusPage: 'Chapter 3: Publications' 5 | --- 6 | 7 | ## Stop using them 8 | 9 | Yes you read that right, unless you want to create a custom functionality that uses the beautiful LiveData utilities 10 | from Meteor, stop using publications, instead leverage [Grapher](http://grapher.cultofcoders.com) for this. 11 | 12 | 13 | If you would like to find one post and have it react to changes you will create a NamedQuery: 14 | 15 | ```js 16 | // file: /imports/db/posts/queries/getPost.js 17 | export default Posts.createQuery('getPost', { 18 | $filter({filters, params}) { 19 | filters._id = params.postId; 20 | }, 21 | title: 1, 22 | user: { 23 | profile: 1, 24 | } 25 | }); 26 | ``` 27 | 28 | ```js 29 | // file: /imports/api/posts/queries/getPost.expose.js 30 | // if you don't expose it you can't work with it 31 | import getPost from './getPost'; 32 | 33 | getPost.expose({ 34 | firewall(userId, params) { 35 | // some rules here to secure the query 36 | } 37 | }) 38 | ``` 39 | 40 | In the client you will use it something like this: 41 | 42 | ```js 43 | import getPostQuery from '/imports/db/posts/queries/getPost'; 44 | 45 | export default createContainer(({postId}) => { 46 | const query = getPostQuery.clone({postId}); 47 | const handle = query.subscribe(); 48 | 49 | return { 50 | ready: handle.ready(), 51 | post: query.fetchOne(), 52 | }; 53 | }) 54 | ``` 55 | 56 | The advantages are the following: 57 | - No need to do big changes if you decide to make a query non-reactive 58 | - Separates the concern of data fetching 59 | - Brings modularity and easy linking with other collections. 60 | 61 | You have to use [Grapher](http://grapher.cultofcoders.com/index.html) in your Meteor app if you want to bring it to enterprise standards. Period. It's the best way we know. 62 | 63 | -------------------------------------------------------------------------------- /themes/meteor/layout/partials/sidebar.ejs: -------------------------------------------------------------------------------- 1 |