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 create book from Github repo.
- 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.
- Admin demo
- Run locally
- Deploy
- Screenshots
- Built with
- Project structure
- Book
- Contributing
- Team
- License
-
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.
.
├── 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
│ ├── stripe.js # Stripe API
├── static # Static resources
├── 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
├── env-config.js # Make Stripe's public keys available on client
├── now.json # Settings for now from Zeit
├── package.json # List of packages and scripts
├── yarn.lock # Exact versions of packages. Generated by yarn.
We wrote this book that teaches you how to build the web app in this repository from scratch. In the book, you'll start from 0 lines of code in Chapter 1 and end up with over 12,000 lines of code by Chapter 8.
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.