3

Apologies for the basic question, but I can't figure out why the CSS sheet called out in my base template's header isn't hooked up when I check my index.html file on http.server.

I'm migrating my site to Python and Jinja, no frameworks.

I built a server module/script based on some tutorials I found online:

# server.py
import os
import http.server
import socketserver
from jinja2 import Environment, FileSystemLoader

PORT = 8000
STATIC_DIR = "static/"

class StaticFileHandler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=STATIC_DIR, **kwargs)

with socketserver.TCPServer(("", PORT), StaticFileHandler) as httpd:
    print(f"Serving at http://localhost:{PORT}/")
    httpd.serve_forever()

The base template's header looks like this (omitting the rest of the template's code as I don't think it's relevant here):

<!DOCTYPE html>
<html lang="en-us">
    <head>
        <meta charset="utf-8">
            <title>{% block title %}{% endblock title %}</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="robots" content="noai, noimageai, noarchive">
            <link rel="icon" type="image/x-icon" href="favicon.ico">
            <link rel="stylesheet" href="styles.css">
    </head>

I've also tried writing the paths to the static files as "static/styles.css" and so on, but no luck there. What am I missing? I feel like (and hope) this is just some dumb oversight that's right under my nose and I'm not seeing it, but...well, I've wracked my brain on this and just can't see it. Any ideas?

Also: in server.py, what do I enter for STATIC_DIR if I want the project's home folder to be the static directory (just for testing purposes for now)? I thought leaving it blank or just adding / would do the trick, but those seem to show me my computer's root directory, not the project's, and obviously I don't want that.

Perhaps a better question is: how would I set up server.py so it pulls static files like CSS, fonts, etc. from STATIC_DIR, but looks for index.html from a different directory (like the project folder, or maybe a site folder since I plan on making an output folder for all the HTML files to upload, like a static site generator?

EDIT: I should include my current test script for generating the index.html file. It saves the HTML file to the project folder, but I just drag it to static for testing:

# write-posts.py
from jinja2 import Environment, FileSystemLoader
from datetime import datetime, timezone

# date = datetime(tzinfo=timezone.utc).isoformat()
posts = [
    {"title": "First Post", "slug": "first-post", "date": "2025, 7, 1", "body": "First post!", "tags": "First Post"},
]

environment = Environment(loader=FileSystemLoader("templates"))
template = environment.get_template("index.html")
filename = "index.html"

content = template.render(posts=posts)

with open(filename, mode="w", encoding="utf-8") as message:
        message.write(content)
        print(f"... wrote {filename}")
3
  • did you try to use styles.css without static/ ? Maybe it searchs file STATIC_DIR + static/styles.css which gives static/static/styles.css. OR you should create files static/static/style.css to get it in HTML as static/style.css. If I run your server without index.html then it shows me all files in folder and it can loads http://localhost:8000/styles.css when I have on disk static/style.css
    – furas
    Commented 11 hours ago
  • or maybe you should change folder names to make it less confusing. If you create folder resource and file resource/static/style.css and STATIC_DIR="resource/" then if you use HTML with static/style.css then server will search resource/static/style.css
    – furas
    Commented 11 hours ago
  • or maybe you shouldn't use name STATIC_DIR because it is missleading. It is rather BASE_DIR - and it could be BASE_DIR="www" and folder www/ with www/index.html and www/static/style.css
    – furas
    Commented 11 hours ago

2 Answers 2

0

I think name of variable STATIC_DIR is missleading and it can confuse with folder name static.

As for me it should have name BASE_DIR and you could have folder www/ or html/ like in real WWW servers.

So your structure could be

project/
  +-> server.py
  +-> www/
       +-> index.html
       +-> static/
            +-> style.css
            +-> script.js
       +-> posts/
            +-> 1.html
            +-> 2.html         

And code could use BASE_DIR = "www/" or even better BASE_DIR="/full/path/to/www/" because you may run server from different current working directory.

(frankly, even name StaticFileHandler can be missleading because it is handler for all files on server, not only in folder static. To server only static files it would need something more complex, and it would need something else to serve other files - like .html)

server.py

import os
import http.server
import socketserver
from jinja2 import Environment, FileSystemLoader

PORT = 8000
BASE_DIR = "www/"

class StaticFileHandler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=BASE_DIR, **kwargs)

with socketserver.TCPServer(("", PORT), StaticFileHandler) as httpd:
    print(f"Serving at http://localhost:{PORT}/")
    httpd.serve_forever()

And html could use static/style.css or even better with leading / like /static/style.css if you would like to use it also in html in subfolders like posts/1.html

index.html

<!DOCTYPE html>
<html>
<head>
   <link rel="stylesheet" type="text/css" href="/static/style.css">
</head>
<body>
   <a href="/posts/1.html">Post 1</a><br/>
   <a href="/posts/2.html">Post 2</a><br/>
</body>
</html>
0

It is a simple fix: your CSS not loading because your server only serving from static/, but your HTML is outside.

You can do this:

  1. Move your index.html to static/ folder.

  2. In base template:

    <link rel="stylesheet" href="styles.css">

Or better:

Keep HTML in a site/ folder and Keep CSS in static/

And then just change server.py:

class CustomHandler(http.server.SimpleHTTPRequestHandler): 
    def __init__(self, *args, **kwargs): 
        super().__init__(*args, directory="site", **kwargs) 
 
    def translate_path(self, path): 
        if path.endswith(".css"): 
            return os.path.join(os.getcwd(), "static", path.lstrip("/")) 
        return super().translate_path(path)

I can't find the my file where i faced the same issue, but that was a Django project so I just used ChatGPT here, i guess this would give you rough idea about the static/ path.

2
  • Your first answer shows you didn't read my post, because if you did, you'd see that I already moved index.html to the static folder. Your second answer doesn't look like it would solve anything, and since you said it's what ChatGPT farted out, I'm willing to bet that I'm right. I don't have enough reputation to downvote, but consider this a downvote. Commented 15 hours ago
  • 2
    Also, ChatGPT violates site policy: meta.stackoverflow.com/questions/421831/… Commented 15 hours ago

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.