 (defun skewer-bower-package-versions (package)
   "List the available versions for a package."
   (skewer-bower-package-ensure package)
-  (sort (skewer-bower-git-tag package) #'string<))
+  (or (sort (skewer-bower-git-tag package) #'string<)
+      (list "master")))
 
 (defun skewer-bower-get-config (package &optional version)
-  "Get the configuration for a package."
+  "Get the configuration alist for PACKAGE at VERSION."
   (skewer-bower-package-ensure package)
+  (unless version (setf version "master"))
   (json-read-from-string
-   (skewer-bower-git-show package (or version "master") "bower.json")))
+   (or (skewer-bower-git-show package version "bower.json")
+       (skewer-bower-git-show package version "package.json")
+       (skewer-bower-git-show package version "component.json")
+       "null")))
 
 ;; Serving the library
 
+(defvar skewer-bower-history ()
+  "Library selection history.")
+
+(defun skewer-bowser--path (package version main)
+  "Return the hosted path for PACKAGE."
+  (format "/skewer/bower/%s/%s/%s" package (or version "master") main))
+
+;;;###autoload
 (defun skewer-bower-load (package &optional version)
-  "Dynamically load a library from bower into the page."
+  "Dynamically load a library from bower into the current page."
   (interactive
    (let* ((packages (mapcar #'car skewer-bower-packages))
-          (package (completing-read "Library: " packages nil t))
+          (selection (delete-duplicates
+                      (append skewer-bower-history packages) :from-end t))
+          (package (completing-read "Library: " selection nil t nil
+                                    'skewer-bower-history))
           (versions (skewer-bower-package-versions package))
-          (version (completing-read "Version: " (reverse versions) nil t)))
+          (version (completing-read "Version: " (reverse versions))))
      (list package version)))
   (let* ((config (skewer-bower-get-config package))
+         (deps (cdr (assoc 'dependencies config)))
          (main (cdr (assoc 'main config))))
-    (skewer-eval (concat "/skewer/bower/" package "/" (or version "master")
-                         "/" main) nil
-                 :type "script")))
+    (unless main
+      (error "Could not load %s (%s)" package version))
+    (loop for (dep . version) in deps
+          do (skewer-bower-load (format "%s" dep) version))
+    (let ((path (skewer-bowser--path package version main)))
+      (skewer-eval path nil :type "script"))))
 
 (defservlet skewer/bower application/javascript (path)
   "Serve a file from the local repository cache."

      (not (null status)))))

(defun skewer-bower-git-show (package version file)
  "Show a file from a repository."
  (skewer-bower-git package "show" (format "%s:%s" version file)))

(defun skewer-bower-git-tag (package)
  "List all the tags in a repository."
  (split-string (skewer-bower-git package "tag")))

;; Bower functions

  "Alist of all packages known to bower.")

(defvar skewer-bower-refreshed nil
  "List of packages that have been refreshed recently. This keeps
them from hitting the network frequently.")

;;;###autoload
(defun skewer-bower-refresh ()
  "Update the package listing and packages synchronously."
  (setf skewer-bower-refreshed nil)
  (with-current-buffer
      (url-retrieve-synchronously (concat skewer-bower-endpoint "/packages"))
