diff --git a/bee.json b/bee.json
index 40050dd581..e4a0f803d3 100644
--- a/bee.json
+++ b/bee.json
@@ -11,7 +11,8 @@
 		"controllers": "routers",
 		"models": "",
 		"others": [
-			"utils"
+			"utils", "modules",
+			"$GOPATH/src/github.com/gogits/binding"
 		]
 	},
 	"cmd_args": [
diff --git a/conf/app.ini b/conf/app.ini
index dcc58c37f3..3d4a259327 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -3,6 +3,7 @@ RUN_USER = lunny
 
 [repository]
 ROOT = /Users/lunny/git/gogs-repositories
+ROOT_jiahuachen = /Users/jiahuachen/git/gogs-repositories
 
 [server]
 HTTP_ADDR = 
diff --git a/gogs.go b/gogs.go
index 72a967f01c..1ce0f7f98e 100644
--- a/gogs.go
+++ b/gogs.go
@@ -19,7 +19,7 @@ import (
 // Test that go1.1 tag above is included in builds. main.go refers to this definition.
 const go11tag = true
 
-const APP_VER = "0.0.0.0303"
+const APP_VER = "0.0.0.0305"
 
 func init() {
 	runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/models.go b/models/models.go
index d07b1fe384..0dee65478f 100644
--- a/models/models.go
+++ b/models/models.go
@@ -83,6 +83,9 @@ func setEngine() {
 	//log.Trace("Initialized database -> %s", dbName)
 
 	RepoRootPath = utils.Cfg.MustValue("repository", "ROOT")
+	if uname.Username == "jiahuachen" {
+		RepoRootPath = utils.Cfg.MustValue("repository", "ROOT_jiahuachen")
+	}
 }
 
 func init() {
diff --git a/models/user.go b/models/user.go
index 820597380d..d8469251e9 100644
--- a/models/user.go
+++ b/models/user.go
@@ -15,7 +15,6 @@ import (
 	"github.com/dchest/scrypt"
 
 	"github.com/gogits/gogs/utils"
-	"github.com/gogits/gogs/utils/log"
 )
 
 // User types.
@@ -100,17 +99,15 @@ func RegisterUser(user *User) (err error) {
 	user.LowerName = strings.ToLower(user.Name)
 	user.Avatar = utils.EncodeMd5(user.Email)
 	user.EncodePasswd()
-	_, err = orm.Insert(user)
-	if err != nil {
+	if _, err = orm.Insert(user); err != nil {
 		return err
 	}
 
-	err = os.MkdirAll(UserPath(user.Name), os.ModePerm)
-	if err != nil {
-		_, err2 := orm.Id(user.Id).Delete(&User{})
-		if err2 != nil {
-			log.Error("create userpath %s failed and delete table record faild",
-				user.Name)
+	if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
+
+		if _, err := orm.Id(user.Id).Delete(&User{}); err != nil {
+			return errors.New(fmt.Sprintf(
+				"both create userpath %s and delete table record faild", user.Name))
 		}
 		return err
 	}
diff --git a/modules/auth/form.go b/modules/auth/form.go
new file mode 100644
index 0000000000..9094ef5c32
--- /dev/null
+++ b/modules/auth/form.go
@@ -0,0 +1,111 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package auth
+
+import (
+	"net/http"
+	"reflect"
+
+	"github.com/codegangsta/martini"
+
+	"github.com/gogits/binding"
+
+	"github.com/gogits/gogs/modules/base"
+	"github.com/gogits/gogs/utils/log"
+)
+
+type RegisterForm struct {
+	UserName string `form:"username" binding:"Required;AlphaDash;MinSize(5);MaxSize(30)"`
+	Email    string `form:"email" binding:"Required;Email;MaxSize(50)"`
+	Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
+}
+
+func (r *RegisterForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
+	if req.Method == "GET" || errors.Count() == 0 {
+		return
+	}
+
+	data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
+	data["HasError"] = true
+	AssignForm(r, data)
+
+	if len(errors.Overall) > 0 {
+		for _, err := range errors.Overall {
+			log.Error("RegisterForm.Validate: %v", err)
+		}
+		return
+	}
+
+	if err, ok := errors.Fields["UserName"]; ok {
+		data["Err_Username"] = true
+		switch err {
+		case binding.RequireError:
+			data["ErrorMsg"] = "Username cannot be empty"
+		case binding.AlphaDashError:
+			data["ErrorMsg"] = "Username must be valid alpha or numeric or dash(-_) characters"
+		case binding.MinSizeError:
+			data["ErrorMsg"] = "Username at least has 5 characters"
+		case binding.MaxSizeError:
+			data["ErrorMsg"] = "Username at most has 30 characters"
+		default:
+			data["ErrorMsg"] = "Unknown error: " + err
+		}
+		return
+	}
+
+	if err, ok := errors.Fields["Email"]; ok {
+		data["Err_Email"] = true
+		switch err {
+		case binding.RequireError:
+			data["ErrorMsg"] = "E-mail address cannot be empty"
+		case binding.EmailError:
+			data["ErrorMsg"] = "E-mail address is not valid"
+		case binding.MaxSizeError:
+			data["ErrorMsg"] = "E-mail address at most has 50 characters"
+		default:
+			data["ErrorMsg"] = "Unknown error: " + err
+		}
+		return
+	}
+
+	if err, ok := errors.Fields["Password"]; ok {
+		data["Err_Passwd"] = true
+		switch err {
+		case binding.RequireError:
+			data["ErrorMsg"] = "Password cannot be empty"
+		case binding.MinSizeError:
+			data["ErrorMsg"] = "Password at least has 6 characters"
+		case binding.MaxSizeError:
+			data["ErrorMsg"] = "Password at most has 30 characters"
+		default:
+			data["ErrorMsg"] = "Unknown error: " + err
+		}
+		return
+	}
+
+}
+
+// AssignForm assign form values back to the template data.
+func AssignForm(form interface{}, data base.TmplData) {
+	typ := reflect.TypeOf(form)
+	val := reflect.ValueOf(form)
+
+	if typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+		val = val.Elem()
+	}
+
+	for i := 0; i < typ.NumField(); i++ {
+		field := typ.Field(i)
+
+		fieldName := field.Tag.Get("form")
+		// Allow ignored fields in the struct
+		if fieldName == "-" {
+			continue
+		}
+
+		data[fieldName] = val.Field(i).Interface()
+	}
+}
diff --git a/modules/base/base.go b/modules/base/base.go
new file mode 100644
index 0000000000..0d305ab453
--- /dev/null
+++ b/modules/base/base.go
@@ -0,0 +1,20 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package base
+
+import (
+	"github.com/codegangsta/martini"
+)
+
+type (
+	// Type TmplData represents data in the templates.
+	TmplData map[string]interface{}
+)
+
+func InitContext() martini.Handler {
+	return func(context martini.Context) {
+		context.Map(TmplData{})
+	}
+}
diff --git a/routers/user/user.go b/routers/user/user.go
index a66a7b5f94..503ebf54f4 100644
--- a/routers/user/user.go
+++ b/routers/user/user.go
@@ -8,13 +8,13 @@ import (
 	"fmt"
 	"net/http"
 
+	//"github.com/martini-contrib/binding"
 	"github.com/martini-contrib/render"
 	"github.com/martini-contrib/sessions"
 
-	"github.com/gogits/validation"
-
 	"github.com/gogits/gogs/models"
-	"github.com/gogits/gogs/utils/auth"
+	"github.com/gogits/gogs/modules/auth"
+	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/utils/log"
 )
 
@@ -50,42 +50,42 @@ func SignIn(req *http.Request, r render.Render, session sessions.Session) {
 	})
 }
 
-func SignUp(req *http.Request, r render.Render) {
-	data := map[string]interface{}{"Title": "Sign Up"}
+func SignUp(form auth.RegisterForm, data base.TmplData, req *http.Request, r render.Render) {
+	data["Title"] = "Sign Up"
+
 	if req.Method == "GET" {
 		r.HTML(200, "user/signup", data)
 		return
 	}
 
-	// Front-end should do double check of password.
-	u := &models.User{
-		Name:   req.FormValue("username"),
-		Email:  req.FormValue("email"),
-		Passwd: req.FormValue("passwd"),
-	}
-
-	valid := validation.Validation{}
-	ok, err := valid.Valid(u)
-	if err != nil {
-		log.Error("user.SignUp -> valid user: %v", err)
-		return
-	}
-	if !ok {
-		data["HasError"] = true
-		data["ErrorMsg"] = auth.GenerateErrorMsg(valid.Errors[0])
+	if hasErr, ok := data["HasError"]; ok && hasErr.(bool) {
 		r.HTML(200, "user/signup", data)
 		return
 	}
 
-	// err = models.RegisterUser(u)
-	// if err != nil {
-	// 	r.HTML(200, "base/error", map[string]interface{}{
-	// 		"Error": fmt.Sprintf("%v", err),
-	// 	})
-	// 	return
-	// }
+	//Front-end should do double check of password.
+	u := &models.User{
+		Name:   form.UserName,
+		Email:  form.Email,
+		Passwd: form.Password,
+	}
 
-	// r.Redirect("/")
+	if err := models.RegisterUser(u); err != nil {
+		if err.Error() == models.ErrUserAlreadyExist.Error() {
+			data["HasError"] = true
+			data["Err_Username"] = true
+			data["ErrorMsg"] = "Username has been already taken"
+			auth.AssignForm(form, data)
+			r.HTML(200, "user/signup", data)
+			return
+		}
+
+		log.Error("user.SignUp: %v", err)
+		r.HTML(500, "status/500", nil)
+		return
+	}
+
+	r.Redirect("/user/login")
 }
 
 func Delete(req *http.Request, r render.Render) {
diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl
index e8854e4aca..52e8fe1814 100644
--- a/templates/user/signup.tmpl
+++ b/templates/user/signup.tmpl
@@ -6,20 +6,20 @@
 	{{if .HasError}}
 	<div class="alert alert-danger">{{.ErrorMsg}}</div>
 	{{end}}
-		<div class="form-group">
+		<div class="form-group {{if .Err_Username}}has-error has-feedback{{end}}">
 			<label class="col-md-4 control-label">Username: </label>
 			<div class="col-md-6">
-				<input name="username" class="form-control" placeholder="Type your username">
+				<input name="username" class="form-control" placeholder="Type your username" value="{{.username}}">
 			</div>
 		</div>
-		<div class="form-group">
+		<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}">
 			<label class="col-md-4 control-label">Email: </label>
 			<div class="col-md-6">
-				<input name="email" class="form-control" placeholder="Type your e-mail address">
+				<input name="email" class="form-control" placeholder="Type your e-mail address" value="{{.email}}">
 			</div>
 		</div>
 
-		<div class="form-group">
+		<div class="form-group {{if .Err_Passwd}}has-error has-feedback{{end}}">
 			<label class="col-md-4 control-label">Password: </label>
 			<div class="col-md-6">
 				<input name="passwd" type="password" class="form-control" placeholder="Type your password">
diff --git a/utils/auth/auth.go b/utils/auth/auth.go
deleted file mode 100644
index 1099103403..0000000000
--- a/utils/auth/auth.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package auth
-
-import (
-	"fmt"
-
-	"github.com/gogits/validation"
-)
-
-func GenerateErrorMsg(e *validation.ValidationError) string {
-	return fmt.Sprintf("%v", e.LimitValue)
-}
diff --git a/web.go b/web.go
index ca3b4fcf1a..9055151070 100644
--- a/web.go
+++ b/web.go
@@ -14,6 +14,10 @@ import (
 	"github.com/martini-contrib/render"
 	"github.com/martini-contrib/sessions"
 
+	"github.com/gogits/binding"
+
+	"github.com/gogits/gogs/modules/auth"
+	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/routers"
 	"github.com/gogits/gogs/routers/repo"
 	"github.com/gogits/gogs/routers/user"
@@ -46,6 +50,7 @@ func runWeb(*cli.Context) {
 
 	// Middleware.
 	m.Use(render.Renderer(render.Options{Funcs: []template.FuncMap{AppHelpers}}))
+	m.Use(base.InitContext())
 
 	// TODO: should use other store because cookie store is not secure.
 	store := sessions.NewCookieStore([]byte("secret123"))
@@ -55,7 +60,7 @@ func runWeb(*cli.Context) {
 	m.Get("/", routers.Dashboard)
 	m.Any("/user/login", user.SignIn)
 
-	m.Any("/user/sign_up", user.SignUp)
+	m.Any("/user/sign_up", binding.BindIgnErr(auth.RegisterForm{}), user.SignUp)
 
 	m.Get("/user/profile", user.Profile) // should be /username
 	m.Any("/user/delete", user.Delete)