Builder Book is an open source web app to publish documentation or books. The app is built with React/Material-UI/Next/Express/Mongoose/MongoDB and includes these third party APIs: Google, Github, AWS SES, Mailchimp, Stripe.
- Live app: https://builderbook.org/books/builder-book/introduction.
- Check our Admin demo to edit a book and create your own from a Github repo.
- Learn how to build this app from scratch with our book
- As learning material for React/Material-UI/Next/Express/Mongoose/MongoDB stack and Google/Github/AWS SES/Mailchimp/Stripe APIs. You can start from our boilerplate or modify the final app into your own project.
- As a production-ready web app to publish documentation or sell books on your own website.
-
Fork our demo book repository to use as sample content for the demo.
Important note: Content in the demo-book repo has the proper format to create a book. If you use another repo but don't follow this format, then book creation will not work.
- Any Github repo you use must have a non-empty
introduction.md
file at the root. - The
introduction.md
and any other.md
files with conent must have metadata in the format shown below:
--- title: Introduction seoTitle: title for search engines seoDescription: description for search engines isFree: true ---
- To make the content of a
.md
file private (meaning a person must buy the book to see its content), changeisFree:true
toexcerpt:""
. Add some sample content between the quotes - this content is public and serves as a free preview.
- Any Github repo you use must have a non-empty
-
Log in to our demo app with Google. You'll be logged in as an Admin.
-
After logging in:
- Click
Connect Github
. - Click
Add book
. - Enter details and select the
/demo-book
Github repo that you forked earlier. - Click
Save
. - You are now on the
book-detail
page, where you see links to the Introduction and Chapter 1.
- Click
-
Edit some content in the
introduction.md
andchapter-1.md
files in your/demo-book
repo. -
Go back to the
book-detail
page and clickSync with Github
to update your book.
-
Clone the project and run
yarn
to add packages. -
Before you start the app, create a
.env
file at the app's root. This file must have at least three env variables:MONGO_URL_TEST
,Google_clientID
,Google_clientSecret
.- For
MONGO_URL_TEST
, we recommend a free MongoDB at mLab. - For Google API keys, see the official OAuth tutorial.
To use all features and third-party integrations (such as Stripe, Google OAuth, Mailchimp), add values to all env variables in
.env
file:.env
:MONGO_URL="XXXXXX" MONGO_URL_TEST="XXXXXX" Google_clientID="XXXXXX" Google_clientSecret="XXXXXX" Amazon_accessKeyId="XXXXXX" Amazon_secretAccessKey="XXXXXX" EMAIL_SUPPORT_FROM_ADDRESS="XXXXXX" Github_Test_ClientID="XXXXXX" Github_Test_SecretKey="XXXXXX" Github_Live_ClientID="XXXXXX" Github_Live_SecretKey="XXXXXX" Stripe_Test_SecretKey="XXXXXX" Stripe_Live_SecretKey="XXXXXX" MAILCHIMP_API_KEY="XXXXXX" MAILCHIMP_REGION="XXXXXX" MAILCHIMP_PREORDERED_LIST_ID="XXXXXX" MAILCHIMP_ORDERED_LIST_ID="XXXXXX"
For Google OAuth app, callback URL is: http://localhost:8000/oauth2callback You have to enable Google+ API in your Google Cloud Platform account.
For Github OAuth app, callback URL is: http://localhost:8000/auth/github/callback
- For
-
Before you start the app, create a
env-config.js
file at the app's root. This file makes Stripe's public keys (keys that start withpk
) available on client. Content of this file:env-config.js
:const dev = process.env.NODE_ENV !== 'production'; module.exports = { StripePublishableKey: dev ? 'pk_test_XXXXXX' : 'pk_live_XXXXXX', };
-
Start the app with
yarn dev
. -
The first registered user in the app becomes an Admin user (
"isAdmin": true
).
-
Create a new Github repo (public or private).
-
In that repo, create an
introduction.md
file and write some content. -
At the top of your
introduction.md
file, add metadata in the format shown below. See this file as an example.--- title: Introduction seoTitle: title for search engines seoDescription: description for search engines isFree: true ---
-
Go to the app, click "Connect Github".
-
Click "Add Book". Enter details and select the Github repo you created.
-
Click "Save".
When you add new .md
files or update content, go to the book-detail
page of your app and click Sync with Github
. Note that all .md
files in your Github repo must have metadata in the format shown above.
To make the content of a .md
file private (meaning a person must purchase the content to see it), change isFree:true
to excerpt:""
. Add some sample content between the quotes - this content is public and serves as a free preview.
- Install now:
npm install -g now
. - Point your domain to Zeit world nameservers: three steps.
- Check the
now.json
file. If you are usingdotenv
and.env
for env variables, no need to changenow.json
. If you make changes to the app, check up how to configure now. - Make sure you updated
ROOT_URL
inpackage.json
andlib/getRootURL.js
. - Check that you have all production-level env variables in
.env
. - In your terminal, deploy the app by running
now
. - Now outputs your deployment's URL, for example:
builderbook-zomcvzgtvc.now.sh
. - Point successful deployment to your domain, for example:
now ln builderbook-demo-zomcvzgtvc.now.sh builderbook.org
.
Chapter excerpt with Buy Button for Pubilc/Guest visitor:
Chapter content for book Customer:
Add-book/Edit-book page for Admin user:
Book-detail page for Admin user:
- Google OAuth
- Github
- AWS SES
- Stripe
- MailChimp
Check out package.json.
.
├── boilerplate # Boilerplate with React, Material-UI, Next, Express, Mongoose, MongoDB
├── book # Codebases for each chapter of our book
├── components # React components
│ ├── admin # Components used on Admin pages
│ │ ├── EditBook.js # Edit title, price, and repo of book
│ │ ├── GiveFreeBook.js # Give free book to user
│ ├── customer # Components used on Customer pages
│ │ ├── Bookmark.js # Bookmark a section within a book chapter
│ │ ├── BuyButton.js # Buy book
│ ├── Header.js # Header component
│ ├── HomeFooter.js # Footer component on homepage
│ ├── HomeHeader.js # Header component on homepage
│ ├── MenuDrop.js # Dropdown menu
│ ├── Notifier.js # In-app notifications for app's users
│ ├── SharedStyles.js # List of _reusable_ styles
│ ├── TOC.js # Table of Contents
├── lib # Code available on both client and server
│ ├── api # Client-side API methods
│ │ ├── admin.js # Admin user methods
│ │ ├── customer.js # Customer user methods
│ │ ├── getRootURL.js # Returns ROOT_URL
│ │ ├── public.js # Public user methods
│ │ ├── sendRequest.js # Reusable code for all GET and POST requests
│ ├── context.js # Context for Material-UI integration
│ ├── notifier.js # Contains notify() function that loads Notifier component
│ ├── withAuth.js # HOC that passes user to pages and more
│ ├── withLayout.js # HOC for SSR with Material-UI and more
├── pages # Pages
│ ├── admin # Admin pages
│ │ ├── add-book.js # Page to add a new book
│ │ ├── book-detail.js # Page to view book details and sync content with Github
│ │ ├── edit-book.js # Page to update title, price, and repo of book
│ │ ├── index.js # Main Admin page that has all books and more
│ ├── customer # Customer pages
│ │ ├── my-books.js # Customer's dashboard
│ ├── public # Public pages (accessible to logged out users)
│ │ ├── login.js # Login page
│ │ ├── read-chapter.js # Page with chapter's content
│ ├── _document.js # Allows to customize pages (feature of Next.js)
│ ├── index.js # Homepage
├── server # Server code
│ ├── api # Express routes, route-level middleware
│ │ ├── admin.js # Admin routes
│ │ ├── customer.js # Customer routes
│ │ ├── index.js # Mounts all Express routes on server
│ │ ├── public.js # Public routes
│ ├── models # Mongoose models
│ │ ├── Book.js # Book model
│ │ ├── Chapter.js # Chapter model
│ │ ├── EmailTemplate.js # Email Template model
│ │ ├── Purchase.js # Purchase model
│ │ ├── User.js # User model
│ ├── utils # Server-side util
│ │ ├──slugify.js # Generates slug for any Model
│ ├── app.js # Custom Express/Next server
│ ├── aws.js # AWS SES API
│ ├── github.js # Github API
│ ├── google.js # Google OAuth API
│ ├── logs.js # Logger
│ ├── mailchimp.js # MailChimp API
│ ├── routesWithSlug.js # Express routes that contain slug
│ ├── sitemapAndRobots.js # Express routes for sitemap.xml and robots.txt
│ ├── stripe.js # Stripe API
├── static # Static resources
│ ├── robots.txt # Rules for search engine bots
├── test/server/utils # Tests
│ ├── slugify.test.js # Unit test for generateSlug() function
├── .babelrc # Config for Babel
├── .eslintrc.js # Config for Eslint
├── .gitignore # List of ignored files and directories
├── .npmignore # Files and directories that are not uploaded to the server
├── now.json # Settings for now from Zeit
├── package.json # List of packages and scripts
├── yarn.lock # Exact versions of packages. Generated by yarn.
We welcome suggestions and pull requests, especially for issues labeled as discussion
and contributions welcome
.
By participating in this project, you are expected to uphold Builder Book's Code of Conduct.
All code in this repository is provided under the MIT License.