{"id":47212830,"url":"https://github.com/akshanshgusain/january","last_synced_at":"2026-03-13T15:48:36.238Z","repository":{"id":126509196,"uuid":"609771563","full_name":"akshanshgusain/january","owner":"akshanshgusain","description":"January is Batteries-Included Go Framework inspired by Django. Designed to ease things up for fast development.","archived":false,"fork":false,"pushed_at":"2025-06-10T05:27:15.000Z","size":14942,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-10T06:27:15.850Z","etag":null,"topics":["django","fiber","framework","go","go-gin","go-january","gojanuary","golang","json","middleware","php","rest","rest-api","router","server","web"],"latest_commit_sha":null,"homepage":"https://gojanuary.framer.website/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akshanshgusain.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-03-05T07:21:23.000Z","updated_at":"2025-06-10T05:27:19.000Z","dependencies_parsed_at":"2023-11-06T07:41:55.965Z","dependency_job_id":"5d10fab1-939d-468c-9440-1ecc3079c0f5","html_url":"https://github.com/akshanshgusain/january","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/akshanshgusain/january","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akshanshgusain%2Fjanuary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akshanshgusain%2Fjanuary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akshanshgusain%2Fjanuary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akshanshgusain%2Fjanuary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akshanshgusain","download_url":"https://codeload.github.com/akshanshgusain/january/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akshanshgusain%2Fjanuary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30469469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T11:00:43.441Z","status":"ssl_error","status_checked_at":"2026-03-13T11:00:23.173Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","fiber","framework","go","go-gin","go-january","gojanuary","golang","json","middleware","php","rest","rest-api","router","server","web"],"created_at":"2026-03-13T15:48:35.769Z","updated_at":"2026-03-13T15:48:36.228Z","avatar_url":"https://github.com/akshanshgusain.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://gojanuary.framer.website/\" target=\"_blank\"\u003e\u003cimg src=\"https://github.com/akshanshgusain/january/blob/master/media/logo_dark.png?raw=true\" alt=\"January\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003eJanuary is Batteries-Included Go Framework inspired by Django. Designed to ease things up for fast development.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\n\u003ca href=\"https://gojanuary.akshanshgusain.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/january-docs-blue\" alt=\"January Docs\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://tip.golang.org/doc/go1.18\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/go-mod/go-version/akshanshgusain/january\" alt=\"Supported Go versions\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\n## 🎯 Features\n\n* Robust routing\n* Serve static files\n* Easy access to multiple databases\n* Complete user authentication\n* Database migrations\n* Session support\n* Template engines\n* Generate handlers\n* Middleware support\n* Form Validation\n* CSRF protection\n* Encryption\n* Multiple Caching backends\n\n\n\n\n## 💡 Inspiration\nWhen teams at my organization began transitioning from Python, Node.js, and PHP to Go, we encountered a new challenge: as each developer utilized different libraries, standards, and frameworks, interoperability between teams became increasingly problematic. The January Web Framework was conceived with a \"batteries-included\" approach, enabling teams to swiftly integrate into the Go ecosystem while adhering to consistent standards across the organization.\n\n## 👻 What's New\n1. Built in Support for TailwindCSS.\n2. Supports DaisyUI-Components and Theme.\n3. Added Starter-APP right into the January-CLI\n\n## 👾 WIP\n\n1. **Build with January/January-recipes** a repository of apps build with January framework\n2. **Go January Docs**: [Documentation, coming soon!](https://gojanuary.akshanshgusain.com)\n---\n\n## ⚙️ Installation\n\nJanuary requires **Go version** `1.18` or **higher** to run. If you need to install or upgrade Go, visit the [official Go download page](https://go.dev/dl/). \n\nTo start setting up your project download the **January-CLI** tool\nfrom here [January-CLI](https://github.com/akshanshgusain/january-cli/blob/master/january-cli)\n\n**Problem running [January-CLI](#troubleshooting)?**\n\nor,\n\n**Homebrew installation**: coming soon!\n\n\n## ⚡️ Quickstart\n\nHere is  a basic example to create a simple web app with **January-CLI**:\n```bash\n./january-cli new github.com/your_username/your-repository_name\n```\nThis command creates a new project directory named **your-repository-name**.\nAfter creating the project move the CLI to the project directory :\n\n```bash\nmv ./january-cli ./your-repository-name\n```\nand cd into the project directory:\n```bash\ncd your-repository-name/\n```\nThe app comes bundled with a Makefile(currently only support macOS). Run the web app running:\n```bash\nmake start\n\n\nBuilding January...\nJanuary built!\nStarting January...\nJanuary started!\nINFO\t2024/09/14 10:53:20 load session called\nINFO\t2024/09/14 10:53:20 Starting January server at http://127.0.0.1:9095/\nINFO\t2024/09/14 10:53:20 Quit the server with control+c\n```\nVisit http://localhost:9095 in your browser to the Home page. You can run the `make stop` command to stop the web server.\n\n```bash\nmake stop\n\n\nStopping January...\nStopped January!\n```\n\n\n## 🏢️ Project Structure\n\n```console\nyour-repository-name/\n│\n├── data/\n│   └── models.go\n│\n├── database/\n│   └── docker-compsoe.yaml\n│\n├── handlers/\n│   ├── handlers.go\n│   └── handlerHelper.go\n│\n├── middleware/\n│   └── middleware.go\n│\n├── migartions/\n│\n├── public/\n│   ├── ico/\n│   └── images/\n│\n├── views/\n│   ├── layouts/\n│   └── home.jet\n│\n├── .gitignore\n├── Makefile\n├── go.mod\n├── init.january.go\n├── januaryAppHelper.go\n├── main.go\n└── README.md\n└── routes.go\n```\n\n\n## 👀 Example Usage\n\nListed below are some of the common use-cases. If you want to see more code examples, please visit our [Build With January repository](https://github.com/gofiber/recipes)\n\n### 📖 **Generate Migration Files**\n\nCreate migration file using the **january-cli**. The following command will create two migration files: **\u003cmigration-name\u003e.up.sql** and **\u003cmigration-name\u003e.down.sql** in the \n```bash\n./january-cli make migration \u003cmigartion-name\u003e\n```\n\n### 📖 **Run Migrations**\n\nRun migrations with the **january-cli**. The following command will run the migration:\n1. Migrate Up: Run the latest up migration:\n```bash\n./january-cli migrate up\n```\n2. Migrate Down: Run the latest down migration:\n```bash\n./january-cli migrate down\n```\n3. Migrate Rest: Run all the down migrations and then run all the up migrations:\n```bash\n./january-cli migrate reset\n```\n\n### 📖 **Generate Model**\n\nCreate a model with **january-cli**. The following command will create a `model-name.go` file in the data directory: \n```bash\n./january-cli make model \u003cmodel-name\u003e\n```\nBy default the Models are generate with [Upper](https://upper.io/v4/) DAL to access the Database. After generating the `modelname.go` it needs to me added to the **Model struct** in the `data/models.go`.\n```Go\nvar db *sql.DB\nvar upper db2.Session\n\ntype Models struct {\n\t// any models inserted here (and in the new function)\n\t// are easily accessible throughout the entire application\n\tModelNames  ModelName   // \u003c---- your Model(s)\n}\n\nfunc New(databasePool *sql.DB) Models {\n\tdb = databasePool\n\n\tswitch os.Getenv(\"DATABASE_TYPE\") {\n\tcase \"mysql\", \"mariadb\":\n\n\t\tupper, _ = mysql.New(databasePool)\n\tcase \"postgres\", \"postgresql\":\n\n\t\tupper, _ = postgresql.New(databasePool)\n\tdefault:\n\t\t// do nothing\n\t}\n\n\treturn Models{\n        ModelNames:  ModelName{},\n\t}\n}\n```\nNow, your models are ready to use. The Models come with pre-build CRUD methods:\n```Go\n// ModelName struct\ntype ModelName struct {\n    ID        int       `db:\"id,omitempty\"`\n    CreatedAt time.Time `db:\"created_at\"`\n    UpdatedAt time.Time `db:\"updated_at\"`\n}\n\n// Table returns the table name\nfunc (t *ModelName) Table() string {\n    return \"modelnames\"\n}\n\n// GetAll gets all records from the database, using upper\nfunc (t *ModelName) GetAll(condition up.Cond) ([]*ModelName, error) {\n    collection := upper.Collection(t.Table())\n    var all []*ModelName\n\n    res := collection.Find(condition)\n    err := res.All(\u0026all)\n    if err != nil {\n        return nil, err\n    }\n\n    return all, err\n}\n\n// Get gets one record from the database, by id, using upper\nfunc (t *ModelName) Get(id int) (*ModelName, error) {\n    var one ModelName\n    collection := upper.Collection(t.Table())\n\n    res := collection.Find(up.Cond{\"id\": id})\n    err := res.One(\u0026one)\n    if err != nil {\n        return nil, err\n    }\n    return \u0026one, nil\n}\n\n// Update updates a record in the database, using upper\nfunc (t *ModelName) Update(m ModelName) error {\n    m.UpdatedAt = time.Now()\n    collection := upper.Collection(t.Table())\n    res := collection.Find(m.ID)\n    err := res.Update(\u0026m)\n    if err != nil {\n        return err\n    }\n    return nil\n}\n\n// Delete deletes a record from the database by id, using upper\nfunc (t *ModelName) Delete(id int) error {\n    collection := upper.Collection(t.Table())\n    res := collection.Find(id)\n    err := res.Delete()\n    if err != nil {\n        return err\n    }\n    return nil\n}\n\n// Insert inserts a model into the database, using upper\nfunc (t *ModelName) Insert(m ModelName) (int, error) {\n    m.CreatedAt = time.Now()\n    m.UpdatedAt = time.Now()\n    collection := upper.Collection(t.Table())\n    res, err := collection.Insert(m)\n    if err != nil {\n        return 0, err\n    }\n\n    id := getInsertID(res.ID())\n\n    return id, nil\n}\n\n// Builder is an example of using upper's sql builder\nfunc (t *ModelName) Builder(id int) ([]*ModelName, error) {\n    collection := upper.Collection(t.Table())\n\n    var result []*ModelName\n\n    err := collection.Session().\n        SQL().\n        SelectFrom(t.Table()).\n        Where(\"id \u003e ?\", id).\n        OrderBy(\"id\").\n        All(\u0026result)\n    if err != nil {\n        return nil, err\n    }\n    return result, nil\n}\n```\n\n\n### 📖 **Create APIs**\n\n1. Connect to your **Postgres** database by supplying these values in the `.env` file\n\n    ```.dotenv\n    DATABASE_TYPE=postgres\n    DATABASE_HOST=localhost\n    DATABASE_PORT=5432\n    DATABASE_USER=postgres_use\n    DATABASE_PASS=postgres_password\n    DATABASE_NAME=postgres_db\n    DATABASE_SSL_MODE=disable\n    ```\n2. Write your routes in the `routes.go`:\n    ```Go\n   func (a *application) routes() *chi.Mux {\n        // GET\n        a.get(\"/api/your-get-route\", a.Handlers.GetHandler)\n        // POST\n        a.post(\"/api/your-post-route\", a.Handlers.PostHandler)\n        // PUT\n        a.put(\"/api/your-put-route\", a.Handlers.PutHandler)\n        // PATCH\n        a.patch(\"/api/your-patch-route\", a.Handlers.PatchHandler)\n        // DELETE\n        a.delete(\"/api/your-delete-route\", a.Handlers.DeleteHandler)\n   }\n    ```\n3. Create a **Handler** and write your business login:\n    Create a handler using the **january-cli**: \n    ```bash\n   ./january-cli make handler \u003cyour-handler-name\u003e\n    ```\n   The above command will create a handler named: `your-handler-name.go` in the **handlers** directory.\n    ```Go\n   func (h *Handlers) GetHandler(w http.ResponseWriter, r *http.Request) {\n            // Get path parameter\n            pathParamVar := chi.URLParam(r, \"pathParamVar\")\n\n            // Get query parameters\n            queryParamVar := r.URL.Query().Get(\"queryParamVar\")\n            \n            // Business Logic goes here:\n             ...\n      \n             // declare return response struct\n            var resp struct {\n                    Error   bool   `json:\"error\"`\n                    Message string `json:\"message\"`\n                    Value   string `json:\"value\"`\n                }\n\t\t\t\t   \n             resp.Error = false\n             resp.Message = \"Success\"\n             resp.Value = fromCache.(string)\n       \n             _ = h.App.WriteJson(w, http.StatusOk, resp)\n   } \n    ```\n   \n## 📆 Broken Features\n1. I will be removing the Jet Templating support, the standard library support for templating is decent.\n\n## 📆 Upcoming Features\n1. MariaDB support\n2. Live-reloads \n3. Automatic Swagger Documentation\n4. File system support\n5. Support for Websockets, GraphQL and gRPC\n\n## Troubleshooting\n### 🍎 Opening Unsigned Applications on macOS\nNote: You may need to change permissions.\n\n1. Go to the Apple menu (🍎) in the top-left corner of your screen.\n2. Select \"System Preferences\" (or \"System Settings\" on newer macOS versions).\n3. Click on \"Security \u0026 Privacy\" (or just \"Privacy \u0026 Security\").\n4. In the \"General\" tab, look for a message near the bottom that says \"january-cli was blocked from use because it is not from an identified developer\" (if you don't see this message, try to open the app again).\n5. Click the \"Open Anyway\" button next to this message. You might need to click the lock icon and enter your password to make changes.\n6. A pop-up window will appear asking if you're sure you want to open the application. Click \"Open\" to run the app.\n7. The app should now open, and macOS will remember your choice, allowing you to open the app normally in the future.\n\nAlternative Method: Using Terminal:\n```console\nxattr -d com.apple.quarantine /path/to/downloaded/exectable/january-cli\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakshanshgusain%2Fjanuary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakshanshgusain%2Fjanuary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakshanshgusain%2Fjanuary/lists"}