8.1 KiB
Upstream GanjoorService doc, kept for reference; Divan's own setup is in the root README.
Running GanjoorService Locally — A Beginner's Guide
This walks through getting the whole GanjoorService solution — the API backend (RMuseum) and
the public site (GanjooRazor) — running on your own machine, with real poetry content in it.
What you need first
- Windows.
RMuseumandGanjooRazorboth targetnet10.0-windows7.0and rely on SQL Server LocalDB — both are Windows-specific, so this project doesn't currently build or run on Linux/macOS as-is. - Visual Studio 2022 or newer, with the "ASP.NET and web development" workload installed. That workload also brings in IIS Express and SQL Server Express LocalDB, both of which this guide relies on.
- Git.
- .NET 10 SDK — a recent enough Visual Studio installs this for you; run
dotnet --versionto confirm.
1. Clone and open the solution
git clone https://github.com/ganjoor/GanjoorService.git
Open GanjoorService.sln in Visual Studio. The solution has three web projects:
| Project | What it is |
|---|---|
RMuseum |
The backend API (ASP.NET Core Web API) — everything else talks to this |
GanjooRazor |
The public-facing ganjoor.net website (Razor Pages) |
TajikGanjoor |
The Tajik-script (Cyrillic) mirror site — optional for local dev |
2. Point GanjooRazor at your local API
Open GanjooRazor/appsettings.json (or, better, GanjooRazor/appsettings.Development.json, so
you never risk accidentally committing a local URL). By default it points at the live
production API:
"APIRoot": "https://api.ganjoor.net",
"GlobalAPIRoot": "https://api.ganjoor.net",
Change both to your local RMuseum address instead. http://localhost:3439 is RMuseum's default
IIS Express URL (see RMuseum/Properties/launchSettings.json):
"APIRoot": "http://localhost:3439",
"GlobalAPIRoot": "http://localhost:3439",
SiteUrl already defaults to http://localhost:33081 (GanjooRazor's own IIS Express URL) and
normally doesn't need changing.
If you skip this step, your local site will still run — but it'll be reading and writing the real production ganjoor.net data instead of your own local database, which is almost never what you want for local development.
3. Database
RMuseum/appsettings.json already points at a local SQL Server LocalDB instance by default:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=museum;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"DatabaseMigrate": "True",
With DatabaseMigrate set to "True", RMuseum applies EF Core migrations automatically on
startup, creating the (empty) museum database the first time it runs. You don't need to run any
migration commands by hand.
Two folders it also expects to exist and be writable:
"PictureFileService": {
"StoragePath": "C:\\museum",
"TrashStoragePath": "C:\\museum-trash"
},
"DataProtectionPersistPath": "C:\\Keys",
Create C:\museum, C:\museum-trash, and C:\Keys (or point these settings somewhere more
convenient) before your first run.
4. Set up multiple startup projects
You need both RMuseum (the API) and GanjooRazor (the site) running at once. Right-click the
GanjoorService solution in Solution Explorer → Properties → Common Properties → Startup
Project → Multiple startup projects, and set:
| Project | Action |
|---|---|
RMuseum |
Start without debugging |
GanjooRazor |
Start |
TajikGanjoor |
None |
("Start without debugging" for RMuseum just means you won't be stepping through its code with breakpoints — it still runs fine. Set it to "Start" too if you want to debug the API itself.)
For each project, also make sure its debug target (the dropdown next to the green ▶ button, or Project Properties → Debug) is set to IIS Express, not the plain "Project"/Kestrel profile — the ports above (3439 / 33081) are IIS Express's. The plain Kestrel profile for both projects defaults to the same port (5000), which will collide if you run both at once.
5. First run
Press F5 (or Ctrl+F5). Both projects start, and a browser opens to GanjooRazor's home page.
Since the database is brand new and empty, you'll be redirected — first to a login/signup page (if you're not already logged in), then automatically to an admin data-import page:
This is expected, not an error — an empty database has no poets yet, so there's nothing to show on the home page, and Ganjoor routes you here instead of showing a broken page.
6. Log in as admin
You don't need a separate signup step for the very first account. RSecurityBackend (the
library RMuseum uses for user management) creates the first user automatically the first time
you log in with the email address configured as RSecurityBackend:FirstUserEmail in
RMuseum/appsettings.json — by default:
"RSecurityBackend": {
"FirstUserEmail": "admin@ganjoor.net"
}
Just go to /login and enter that email with any password meeting the site's password
requirements — that first login creates the account and makes it the site's admin. (You can use a
different email if you'd rather — just update FirstUserEmail to match before your first login.)
7. Import real content
On the import page you landed on in step 5 (or reach it any time via Admin → مالی و سایت → درونریزی دادهٔ عمومی), you have two choices for where to read data from:
- Internet URL — the easiest option, nothing to download first:
https://cdn.jsdelivr.net/gh/ganjoor/ganjoor-data@main/ - Local folder — if you've already run
git clone https://github.com/ganjoor/ganjoor-data.gitsomewhere on disk, point it at that folder instead. Faster for repeated imports, and doesn't depend on your internet connection each time you run it.
Poet id — leave it at 0 to import every poet (the full corpus; can take a while), or enter a
specific poet's numeric id to import just that one for quicker local testing. Poet ids start at
2, not 1.
Click شروع درونریزی ("start import"). The job runs in the background — track its progress on the Admin → کارها (Jobs) page. It also regenerates the century groupings the home page needs right after importing (the same thing the "بازسازی گروهبندی بر اساس قرن" button on the Poets admin page does) — you don't need to run that separately. Once the job finishes, refresh the home page: your local Ganjoor now has real poets, poems, and categories in it.
Re-running the import later (e.g. to pick up a poet you skipped the first time) is always safe — it only adds what's missing, and never duplicates or overwrites content already in your database.
Troubleshooting
- RMuseum won't start / complains about the database — make sure SQL Server Express LocalDB is installed. It's part of Visual Studio's "ASP.NET and web development" workload; if it's missing, add it via the Visual Studio Installer → Individual Components → "SQL Server Express LocalDB".
- GanjooRazor loads but every page errors — almost always means
APIRoot/GlobalAPIRootinGanjooRazor/appsettings.jsonis still pointing athttps://api.ganjoor.netinstead of your local RMuseum address, or RMuseum simply isn't running. Re-check step 2. - "Port already in use" — something else on your machine already has 3439 or 33081. Either
free that port, or change it in the relevant project's
Properties/launchSettings.jsonand updateAPIRoot/GlobalAPIRoot/SiteUrlto match. - The import page 401s / "Unauthorized" — you're logged in as an account that isn't
recognized as admin. Confirm you signed up with the exact email set in
FirstUserEmail.


