Report this

What is the reason for this report?

AstroJS project hosted on DigitalOcean droplet with Nginx – CSS loading as text/html

Posted on September 19, 2025

Hey everyone,

I just hosted my AstroJS project on a DigitalOcean droplet using Nginx. The site loads on the IP address, but only the HTML shows up. The CSS is getting served as text/html instead of text/css.

I tried adjusting the Nginx config file but haven’t had any luck. Has anyone faced the same issue before and found a fix? Would really appreciate some guidance. Its kinda urgent - alankritarya15@gmail.com

Thanks!



This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Heya,

Here’s a list of things you need to check to troubleshoot the issue

1) Make sure Nginx knows MIME types

Open /etc/nginx/nginx.conf and confirm this line exists outside any http {} location overrides:

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    # ...
}
  • If include /etc/nginx/mime.types; is missing, add it.

  • If you see default_type text/html; anywhere (global or in your site config), remove it or set it to application/octet-stream.

2) Check your site’s server block

In /etc/nginx/sites-available/your-site (or /etc/nginx/conf.d/your-site.conf), it should be something like:

server {
    listen 80;
    server_name _;  # or your domain

    root /var/www/astro/dist;  # <— point to your Astro build folder (dist)
    index index.html;

    # Serve static files with correct types (mime.types will handle css/js etc.)
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Optional: tighten caching for assets
    location ~* \.(css|mjs|js|wasm|ico|png|jpg|jpeg|gif|svg|webp|avif|woff2?)$ {
        access_log off;
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }
}

Avoid doing any of the following in your config:

  • add_header Content-Type text/html; (this will force CSS to be HTML)

  • default_type text/html; inside server or location

  • Using a rewrite or return 200 that serves everything through index.html without a try_files check first.

3) Verify the file actually exists in dist

Astro’s static build puts assets in dist/ (often under dist/assets/). Check:

ls -lah /var/www/astro/dist/assets | grep .css

If the CSS isn’t there, run:

cd /var/www/astro && npm run build

Then redeploy/copy the dist/ to the server path you’ve set as root.

4) Test the headers

After making changes:

sudo nginx -t && sudo systemctl reload nginx

Then check:

curl -I http://YOUR_IP/assets/yourfile.css

You should see:

Content-Type: text/css

If it still shows text/html, you likely have an override somewhere. Grep for it:

grep -R "default_type\|Content-Type" /etc/nginx -n

Remove any bad default_type text/html; or add_header Content-Type ... lines affecting static paths.

5) Common gotchas

  • Wrong root: If root points to your project folder instead of /dist, Nginx may hit your SPA fallback and serve index.html for everything (hence text/html).

  • Catch-all location first: A broad location / { try_files ... /index.html; } defined above your static file location can intercept .css requests. Keep the asset location ~* \.(css|js|…) block above or ensure try_files returns the static file before falling back.

  • SSR adapter: If you used an Astro Node adapter (SSR) but you’re serving only with Nginx, switch to a static build (no SSR) or proxy to the Node server properly.

Minimal working example

If you want a super minimal config that “just works” for a static Astro build:

server {
    listen 80;
    server_name _;

    root /var/www/astro/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

(Plus the include /etc/nginx/mime.types; in nginx.conf.)


If you paste your current server block, I can spot the exact culprit—but the steps above usually fix it fast.

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.