Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Build a Simple Dynamic Site with Node.js HTTP Methods and Headers Perfection Suggestions

Serve CSS Files (Completed) - the way Andrew taught it

I reverse engineered the way Andrew taught the section for the rest of the application. Include a link to the css file (mine is in a separate folder 'styles'):

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Treehouse Profile</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="./styles/main.css"/>
</head>
<body>

Create a new function for the css files in renderer.js and make sure to export the module:

function css(templateName, response) {
  //Read from the template file
  var fileContents = fs.readFileSync('./styles/' + templateName + '.css', {encoding: "utf8"});
  //Write out the contents to the response
  response.write(fileContents);
} 

module.exports.css = css;

In router.js create a function to serve the css file with the template name you gave it:

// Create a function to serve the CSS file
function style(request, response) {
  if (request.url.indexOf(".css") !== -1){
    renderer.css("main", response);
    response.end();
  }
}

module.exports.style = style;

Lastly, in app.js make sure to include it in the http request to create a server:

//Create a web server
var http = require('http');
http.createServer(function (request, response) {
  router.style(request, response);
  router.home(request, response);
  router.user(request, response);
}).listen(3000);
console.log('Server running at http://<workspace-url>/');
Eddie Lam
Eddie Lam
2,681 Points

Hello Jake Geiser I want to ask why are we checking url.indexOf(".css") !== -1 ?

I don't really get the -1 part and the checking if the url has a .css in it...

I am guessing this is how it works: -1 is checking if the requested route is requesting a css file (?)

and the request for the file is triggered when the browser got to the line where's there's a link tag (?) and that the browser will fire a request with an url ending with .css?

it would be great if you could explain the intuition of that to us!

Thank you very much!

2 Answers

Peter Retvari
seal-mask
.a{fill-rule:evenodd;}techdegree
Peter Retvari
Full Stack JavaScript Techdegree Student 8,392 Points

Hi guys, could you please help? I don't know why I keep get this error message and CSS won't load in the port 3000: Here is my total workspace to check everything if needed: https://w.trhou.se/rspa0iluwm Here is my router.js:

var Profile = require("./profile.js");
var renderer = require("./renderer.js");
var queryString = require("querystring");

function style(request, response) {
  if (request.url.indexOf(".css") !== -1){ 
    renderer.css("mystyle", response);
    response.end();
  }
}

module.exports.style = style;


//Handle HTTP route GET / POST / i.e. Homepage
function home(request, response){
  //if the url === "/" and GET
  if(request.url === "/"){
    if(request.method.toLocaleLowerCase()==="get"){
        //show search field
      response.writeHead(200, {'Content-Type': 'text/html'}); 
      renderer.view('header',{}, response);
      renderer.view('search',{},response);
      renderer.view('footer',{},response); 
      response.end();
    }else {
      //if the URL === "/" and POST

       //get the POST data to body
      request.on("data",function(postBody){
       //extract the username
        var query = queryString.parse(postBody.toString());
        response.writeHead(303,{"Location" : "/" + query.username});
        response.end();
        //redirect to the username
      });


    }
  }


}

//Handle HTTP route GET /:username i.e. /peterretvari
function user (request, response) {

  //if the URL === "/" anything, like "/peterretvari"
  var username = request.url.replace("/","");
  if(username.length > 0){
    response.writeHead(200, {'Content-Type': 'text/html'}); 
    renderer.view('header',"html" ,{}, response);
        //get JSON from Treehouse   
    var studentProfile = new Profile(username);
    //on "end"
    studentProfile.on("end", function(profileJSON){ //profileJSON is the actual data from API
    //show the profile
    //store the values which we need
      var values = {
      avatarUrl: profileJSON.gravatar_url,
      username: profileJSON.profile_name,
      badges: profileJSON.badges.length,
      javascriptPoints: profileJSON.points.JavaScript
      }
      //Simple response
        renderer.view('profile', values, response);
        renderer.view('footer',{},response);

        response.end();
    });
    //on "error"
        studentProfile.on("error", function(error){
    //show the error site
        renderer.view('error',{errorMessage: error.message},response);
        renderer.view('search',{},response);
        renderer.view('footer',{},response);
        response.end();
    });

  }
}

module.exports.home = home;
module.exports.user = user;

To be honest I don't understand totally this function:

// Create a function to serve the CSS file
function style(request, response) {
  if (request.url.indexOf(".css") !== -1){
    renderer.css("main", response);
    response.end();
  }
}

module.exports.style = style;

It should be contain a writeHeader with text/css, or not?

Thanks for you help in advance

Peter Retvari
seal-mask
.a{fill-rule:evenodd;}techdegree
Peter Retvari
Full Stack JavaScript Techdegree Student 8,392 Points

Sorry I forgot to include the error message:

         ^                                                                        

TypeError: response.write is not a function
at Object.view (/home/treehouse/workspace/renderer.js:21:14)
at Object.user (/home/treehouse/workspace/router.js:52:14)
at Server.<anonymous> (/home/treehouse/workspace/app.js:13:10)
at emitTwo (events.js:126:13)
at Server.emit (events.js:214:7)
at parserOnIncoming (_http_server.js:634:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:117:17)

Peter Retvari
seal-mask
.a{fill-rule:evenodd;}techdegree
Peter Retvari
Full Stack JavaScript Techdegree Student 8,392 Points

Hi guys, finally I've made it, but still confused with the CSS file. My program only runs if I don't use reponse.end in the style function:

function style(request, response) {
  if (request.url.indexOf(".css") !== -1){
    renderer.css("main", response);

  }
}

Because I was keep getting the error message: "write after end". Is that because the server send the CSS data, the browser loads it and after it ends and get a new order but the browser doesn't want to execute because there was already an ends?

Could you please help with it?

Peter Retvari
seal-mask
.a{fill-rule:evenodd;}techdegree
Peter Retvari
Full Stack JavaScript Techdegree Student 8,392 Points

Sorry for that I ask so many :) Could you someone also help me why we don't have to use this in our function? :

      response.writeHead(200, {'Content-Type': 'text/css'}); 

How the browser knows that it's a css file not an html if we don't tell?