Logo

Deployment

.htaccess Configuration

Everything works locally. But after deployment, reloading "/login" results in a 404 error. Why? Because the server looks for a file named "login", which doesn't exist.

This is a classic issue that happened to me during my first deployment. I clicked through the app: everything worked. I pressed F5 (refresh): 404 Not Found.

The problem: Angular is a Single Page Application (SPA). Physically, there is only one file: the index.html. When you navigate to /dashboard, Angular knows what to do. But an Apache server is "dumb." It looks at the hard drive, searches for dashboard.html, finds nothing, and throws an error.

1. Server Simulator

I built this simulation to visualize the problem. Try accessing /login. Without the rewrite rule, the server fails. With the rule active, it gracefully forwards the request to Angular.

No Config (Default)
example.com
Apache Access Log
Waiting for request...

2. Implementation

We need to teach the server one simple rule: "If you can't find the file physically, just give me the index.html." For Apache servers, we use a configuration file called .htaccess (no file extension!).

Step 1: Create the File

I always place this file in the public/ folder. This ensures it gets copied to the output directory (`dist/`) automatically during `ng build`.

my-angular-project/
├── src/
├── angular.json
├── public/
│ ├── .htaccess New
│ └── favicon.ico

Step 2: The Rewrite Code

Copy this standard snippet into the file. It tells Apache: "Serve real files (images, JS) directly. Forward everything else to index.html."

public/.htaccess
<IfModule mod_rewrite.c>
  RewriteEngine On

  # 1. Real file exists? (Images, CSS, JS)
  # If yes (-f = file, -d = directory): Serve directly.
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^ - [L]

  # 2. Virtual route?
  # Redirect everything else to index.html. Angular handles the rest.
  RewriteRule ^ /index.html [L]
</IfModule>
💡

Subfolders: If your app isn't running on the root domain (domain.com) but in a subfolder (domain.com/myapp/), you might need to add RewriteBase /myapp/ right after turning the engine on.