Skip to content
EGO is a static site generator that depends on Emacs, Git and Org-mode.
Emacs Lisp CSS HTML JavaScript
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.


Type Name Latest commit message Commit time
Failed to load latest commit information.


中文用户可以点击 EGO 中文手册 ~


EGO is a static site generator that depends on Emacs, Git and Org-mode. it originates from Feng Shu’s org-webpage, which is a fork of Kelvin H’s org-page.

EGO provides features below:

  1. Org sources and html files managed by git
  2. Incremental publication (according to git diff command)
  3. Category support (not recommended)
  4. Tags support (auto generated)
  5. RSS support (auto generated)
  6. Search engine support (auto generated)
  7. A beautiful theme
  8. Theme customization support is well (using mustache template)
  9. Commenting (implemented using disqus/duoshuo)
  10. Website traffic analytics (implemented using google analytics)
  11. Index/about page support (auto generated if no default is provided)
  12. Include a tiny emacs web server, which can be used to test publish.
  13. Manage multi-site configs in an emacs session easily.

“Emacs-version >= 24.5” is required.



Use package repo melpa. or git clone it manually.


The follow code is emacs-china ‘s config , you can paste and adjust it to your .emacs file:

;; the following is only needed if you install EGO manually
(add-to-list 'load-path "path/to/EGO")

(require 'ego)

(ego-add-to-alist 'ego-project-config-alist
                 :repository-directory "~/github/"
                 :repository-org-branch "master" ; 源文件所在 branch
                 :repository-html-branch "master" ; html 文件所在 branch
                 :site-domain ""
                 :site-main-title "EMACS-CHINA"
                 :site-sub-title "=============>集思广益"
                 :theme (default)
                 :summary (("years" :year :updates 10) ("authors" :authors) ("tags" :tags))
                 :source-browse-url ("Github" "")
                 :personal-disqus-shortname "emacs-china"
                 ;; :personal-duoshuo-shortname "emacs-china" ; deprecated because of duoshuo inexistence
                 :confound-email nil
                 :ignore-file-name-regexp ""
                 :web-server-docroot "~/webRoot/"
                 :web-server-port 5432)

                 ;; more projects or sites config can be added here


You can find more config options and theirs default values by commands:

C-h v ego-project-config-alist
C-h v ego-config-fallback

Create New Repository

Using the following command to create a new repository:

M-x ego-new-repository

The repository is preliminary, you have to configure the ego-project-config-alist to make it work!

Create New Post

Using the following command to create a new post:

M-x ego-new-post

Test Post

Using the following command to test current opening org-file:

M-x ego-test-current-page

You can see the html version of the org-file in browser.


The simplest way is run:

M-x ego-do-publication

This command will ask you some questions:

  1. Which project do you want to publish?
  2. Choose a job from the jobs below: “1. Test partial publish” “2. Partial publish” “3. Test full publish” “4. Full publish”
  3. (when (2) is partial) Base git commit: HEAD~1 ?
  4. Input checkin messages. (The message won’t be inputted if you have checkined before.)
  5. (when (2) is not “test”) There will be some questions for “publish-config”

CAUTION: When untested publication, anything modified won’t be published.If you want modified contents to be published, just test it before publication.

you can track the process in message buffer and EGO OUTPUT buffer.

Async Publication

You can use async.el package to wrap the command ego-do-publication in order to publish the static site without a wait.

You can find some example about how to use async.el package here : Async.

And here is an example: (There are some important points so that you had better see it.)

(require 'ego)
(require 'async)
(defun ego-async-do-publish (&optional project-name
   (let* ((j (or ego--default-project-name
                 (completing-read "Which project do you want to publish? "
                                   (mapcar 'car ego-project-config-alist))
                                  nil t nil nil ego--last-project-name)))
          (p (y-or-n-p "Action:  [Yes] Test, [No] Tested Publish. "))
          (f (y-or-n-p (format "Publish all org files of \"%s\" project? " j)))
          (b (unless f (read-string "Base git commit: " "HEAD~1")))
          (c (read-string "checkin message (won't show in 'git log' if you have committed all): "))
          (a nil))
     (list j p f b c a)))
  ;; set ego remote push (publish-config)
  (unless test-and-not-publish
    (setq ego--current-project-name project-name)
    (setq ego--last-project-name project-name)
    (setq publish-config
          (ego--git-get-publish-config (ego--get-repository-directory)
                                      (ego--get-config-option :repository-org-branch)
                                      (ego--get-config-option :repository-html-branch))))

  (message "See *EGO OUTPUT* buffer and *emacs* buffer for information")
   `(lambda ()
      ;; load packages and set load-path
      (setq package-user-dir ,(expand-file-name "~/.emacs.d/elpa/"))
      (add-to-list 'load-path ,(expand-file-name "~/github/org-mode/lisp"))
      (add-to-list 'load-path ,(expand-file-name "~/github/org-mode/contrib/lisp" t))
      (add-to-list 'load-path ,ego-load-directory)

      ;;set color-theme
      (add-to-list 'load-path ,(expand-file-name "~/.emacs.d/color-theme-6.6.0"))
      (require 'color-theme-autoloads "color-theme-autoloads")

      ;; set coding-system
      (set-terminal-coding-system 'utf-8-unix)
      (set-keyboard-coding-system 'utf-8-unix)
      (prefer-coding-system 'utf-8-unix)
      (setq save-buffer-coding-system 'utf-8-unix
            coding-system-for-write 'utf-8-unix)

      ;; pre-set ego configurations
      (require 'cl-lib)
      (require 'ego)
      (setq ego-project-config-alist ',ego-project-config-alist)

      ;; Make EGO show svg images
      (require 'ox-html)
      (defun kd/org-html--format-image (source attributes info)
        "Return \"img\" tag with given SOURCE and ATTRIBUTES.
  SOURCE is a string specifying the location of the image.
  ATTRIBUTES is a plist, as returned by
  `org-export-read-attribute'.  INFO is a plist used as
  a communication channel."
           (list :src source
                 :alt (if (string-match-p "^ltxpng/" source)
                           (org-find-text-property-in-string 'org-latex-src source))
                        (file-name-nondirectory source)))
      (advice-add 'org-html--format-image :override #'kd/org-html--format-image)

      ;; without org-to-html if possible
      (unless ,test-and-not-publish
        (if ,base-git-commit
            (setq ego--publish-without-org-to-html 1)
          (setq ego--publish-without-org-to-html 2)))

      ;; ego-do-publication here
      (ego-do-publication ,project-name

      ;; waiting for push remote success or just wait http-server in which case you have to close *emacs* buffer manually
      (while (not ego--async-publish-success)
        (sit-for 1))

      ;; return the result
      (with-current-buffer (get-buffer-create ,ego--temp-buffer-name)
   `(lambda (result)
      (with-current-buffer (get-buffer-create ego--temp-buffer-name)
        (insert (format "*EGO output* should be :\n %s \nego-async-do-publish done!" result))))))

you can track the process in emacs buffer and EGO OUTPUT buffer.


  1. emacs: this is an “of-course” dependency, “version >= 24.5” is required.
  2. org mode: v8.0 is required, please use M-x org-version <RET> to make sure you org mode version is not less than 8.0
  3. git: a free and open source version control system
  4. mustache.el: a mustache templating library for Emacs
  5. htmlize.el: a library for syntax highlighting (usually this library is shipped with emacs)
  6. dash.el: a modern list library for Emacs
  7. ht.el: a modern hash-table library for Emacs
  8. simple-httpd: a web server library in Emacs for test

Known issues

  • CAUTION when there are opened directories in the repository (which don’t contain the repository itself), ego--git-change-branch will mess up the files in the repository. So, close all opened directories in the repository before ego-do-publication .
  • Currently the deletion change handler has not been implemented so if you deleted some org sources, you may have to manually delete corresponding generated html files.
  • URI path change detection is not available. That is, if you make a post with the URI “/blog/2013/03/25/the-old-post-name” and then change this value in your org source, EGO would be unable to detect that this has happened. it will only publish a new html file for you so you need to delete the old html file related to the old URI manually.

Roadmap [2/3]

  • [X] Next/Previous Page links

    Use M-x org-insert-link (Normal key binding is C-c C-l) and choose ego-link: to insert a link to an org file. The link will be exported as hyperlink to the correct html page.

    The function can be applied to the condition of Next/Previous Page links – Get a chain of files in a logical order rather than just a time sequence.

    When reply “Is it a PERVOUS(bi-directional) link? ” with “y” (according to the M-x org-insert-link ego-link: process), you can add the bi-directional link.

    The link is assigned to class “ego_link” with label “span”, you can customize it in CSS.

  • [ ] More themes

    Just maintain a list of hyperlinks to the other themes except the default.

    Now considering using ‘ego-map.el’ which wipes off the restriction of EGO theme customization. But what’s the shape it should be?

  • [X] upload to melpa


Why can’t I publish those org files containning chinese charactors?

Execute src_sh{git ls-tree -r –name-only HEAD} in the repo directory, if the chinese charactor displays like a mass, please execute

git config --global core.quotepath false

and then try again.

You can’t perform that action at this time.