A practical walkthrough of how Know Nepal's Next.js frontend, Spring Boot backend, PostgreSQL database, and scheduled jobs work together to serve a request.

Introduction

Know Nepal is an open knowledge platform that organizes information about Nepal — geography, history, culture, destinations, education, healthcare, and wildlife — into structured, searchable data.

When people ask how the site works, the usual assumption is that everything happens in the browser. In practice, a web application like this is a set of separate parts: a frontend that renders the interface, a backend that holds the application logic, a database that stores the data, and a few supporting services that run on their own. Each part has a different responsibility, and knowing where those boundaries are is what makes the system easier to reason about.

This article follows one request through those parts: what the frontend does, when the backend is involved, when the database is actually queried, and how a scheduled job differs from a normal visit.

Understanding the Architecture

Know Nepal is deployed as three main pieces plus an external trigger.

Frontend — Next.js, React, and TypeScript

The frontend is a Next.js application written in React and TypeScript and deployed on Vercel. It is responsible for rendering the interface — the pages, navigation, cards, and forms a visitor interacts with — and for requesting data when a feature needs it.

Vercel serves the frontend pages and static assets directly. Not every request reaches the backend: a page, an image, or a data file can be served close to the user without touching the application server at all. Only requests for API data are forwarded onward.

The data-fetching pages are client components that call the API over HTTP, using a query library (TanStack Query) on top of axios. Those calls go to paths under /api/v1/... on the same origin, and that detail matters, because it is what sends them through the proxy described below.

Backend — Java 21 and Spring Boot

The backend is a Spring Boot application running on Java 21, deployed on Render. It exposes the API endpoints, enforces the application logic, validates input, applies authorization rules, and — when a feature needs it — queries the database and assembles the response.

Know Nepal's backend is a modular monolith. It is one application, deployed as one unit, organized internally into seven domain modules: geography, education, healthcare, destinations, culture, history, and wildlife. Each module has its own controllers, services, and repositories. This is deliberately not a set of independently deployed microservices. A modular monolith keeps the operational simplicity of a single deployable while still giving each domain a clear boundary in the code, and for a project at this scale that trade-off has been the right one.

Inside a module the code follows the same layering: a controller receives the HTTP request, a service holds the business logic, and a repository talks to the database.

Database — PostgreSQL and Supabase

Supabase hosts the PostgreSQL databases used by the application. PostgreSQL is the database engine — the software that stores the tables and runs the SQL queries. Supabase is a managed service that runs and exposes that engine, so I do not have to operate a database server myself. Supabase is the hosting; PostgreSQL is the database.

The backend connects to these databases and, when a feature needs stored data, queries them, processes the result, and returns only what the frontend needs. Each domain module is backed by its own Postgres database on Supabase, so the modules stay isolated even though they ship inside one application.

Scheduled jobs — an external scheduler

Some work is not started by a visitor at all. An external scheduling service sends an HTTP request to a configured URL on a timer. That request can trigger backend work independently of anyone opening the website.

I want to be precise about what is actually configured. In the repository, the concrete scheduling I can verify is a scheduled GitHub Actions workflow that requests the backend health endpoint every ten minutes, plus an in-app Spring scheduled task that periodically cleans up a rate-limiter map. A hosted scheduler such as cron-job.org plays the same role as that workflow — it calls a URL on a schedule. Because I could not verify a cron-job.org configuration from the source, I describe the mechanism and its role rather than a specific external job.

What Happens When a User Opens Know Nepal?

The diagram below is the map for everything that follows: the frontend, the backend, the database, and the scheduled path.

Architecture diagram of Know Nepal. From left to right: a browser connects to the Next.js frontend hosted on Vercel, which proxies requests under /api to the Spring Boot modular monolith hosted on Render; the backend reads and writes the PostgreSQL databases hosted on Supabase and calls an external AI provider; a separate external scheduled job sends a request to the backend health endpoint on a timer.

Take a concrete case: a visitor opens a province listing or a single province page. The request lifecycle looks like this.

  1. The user enters https://know-nepal.vercel.app/ in the browser.
  2. The browser requests the site, and Vercel serves the relevant Next.js page and its assets.
  3. The frontend displays the interface. If the page needs additional information, it requests it from an API.
  4. For requests under /api/*, the frontend's proxy forwards the call to the Spring Boot backend on Render. In Next.js this is a rewrite that maps /api/:path* to the backend's base URL.
  5. Spring Boot receives the request, routes it to the matching controller, and runs the relevant application logic.
  6. If the operation requires stored data, the backend queries PostgreSQL through its database layer.
  7. PostgreSQL returns the query result to the backend.
  8. The backend processes the result and returns an HTTP response — usually JSON for data APIs.
  9. The frontend receives the response and renders or updates the relevant part of the interface.

The directions matter. The browser talks to the frontend and to the frontend's /api paths; the frontend, through the proxy, talks to the backend; and only the backend talks to the database. The database is never exposed directly to the browser.

It is also worth stating clearly: loading a page is not the same as fetching data from the database. The page, the map data file, and the images can all be served without any database query. The database is involved only when a feature asks the backend for something that is actually stored there.

Does Every Module Use the Backend and Database?

An API is an interface through which a client requests information or asks a system to perform an operation. It is tempting to assume that an API always means a database, but that is not true. In Know Nepal the paths differ by feature:

  • Static content served by the frontend. The interactive geography map draws from a GeoJSON file that ships with the frontend, alongside the site's images. These are served by Vercel and never reach the backend.
  • Search the frontend does itself. The global search starts from a static index embedded in the frontend and ranks it in the browser, so that part needs no network call.
  • Information requested from a backend API. When a query is specific enough, the frontend also calls backend search endpoints to supplement the static index and keep results current.
  • Information retrieved from PostgreSQL by the backend. The province, district, and similar content listings come from controllers that read from the database.
  • Data obtained from an external service. The AI trip planner calls an external AI provider and grounds the plan on data the backend retrieves.

So the honest picture is a mix: some features are pure frontend, some are frontend plus API, some end at the database, and one reaches out to an external provider.

Why Is There No Public Login Page?

Visitors can read everything without an account, and that is deliberate. Three ideas are worth separating:

  • Public access — a visitor can use a feature without signing in.
  • Authentication — the application verifies who a user is.
  • Authorization — the application checks whether that user is allowed to perform an operation.

Public knowledge should be readable by anyone, so there is no visitor login. Authentication and authorization do exist, but for the administrative side: the small admin/CMS area used to manage content. The backend's security configuration makes the boundary explicit.

GET  /api/v1/**                  -> public
POST /api/v1/ai/trip-planner     -> public (rate limited)
POST/PUT/PATCH/DELETE /api/v1/** -> requires the ADMIN role
anything else                    -> denied by default

Admin login verifies a password against a stored BCrypt hash and issues a JSON Web Token; a filter validates that token on later requests and attaches the ADMIN authority. Reads are open, writes are protected, and the trip planner is the one deliberate public write. The absence of a public signup page does not mean there is no backend, no database, or no security — it means the parts that need protecting are the parts that change data.

What About Scheduled Jobs?

Scheduling is a separate flow, and it helps to draw it distinctly:

external scheduler -> configured backend endpoint -> backend processing -> database, if required -> HTTP response

The important difference is the origin of the request. A scheduled request does not come from a visitor's browser. It is an HTTP call made by a scheduler, and the backend handles it like any other request to that endpoint.

In Know Nepal the concrete pieces I could verify are a scheduled GitHub Actions workflow that requests the health endpoint every ten minutes to keep a free-tier service from spinning down, and an in-app scheduled task that trims the rate limiter's in-memory map so it does not grow without bound. A hosted scheduler such as cron-job.org would serve the same purpose as the workflow — hitting a URL on a timer. Since I could not verify a cron-job.org configuration from the source, I am describing its role rather than inventing a specific job.

Engineering Lessons

  • Separating frontend, backend, and database responsibilities makes the system easier to understand and maintain. Each part has one job, and the boundaries are where the interesting decisions live.
  • Tracing a request across the layers is the fastest way to find where something fails. If a page renders but the data is missing, the problem sits between the /api proxy and the database, not in the page markup.
  • An API does not necessarily access a database. Some endpoints return static or computed data, and assuming otherwise sends you to the wrong place when debugging.
  • Public access and administrative authentication serve different purposes. Keeping reads open while protecting writes is a deliberate design, not a missing feature.
  • Architecture diagrams are useful, but the source code is what confirms the implementation. The diagram shows the intended shape; the configuration and the code show what actually runs.

Conclusion

Know Nepal is a Next.js frontend on Vercel, a Spring Boot modular monolith on Render, PostgreSQL hosted on Supabase, and an external scheduler — each with a distinct responsibility. Following a single request through those parts is what turns a stack of technologies into a system I can reason about, debug, and extend. The Know Nepal project is the system this describes.