A overwhelming amount of feedback for Help us redesign the Stack Overflow homepage was: "Keep the way the front page looks, just tweak the question order"

Interesting algorithms were suggested by Kip and radp, but there was no real playground to experiment.

Enter Home Page MiniCollider™ Question Reordinator™

Users with 200 rep or more on Stack Overflow have access, it includes the 3000 last active questions, favorite tags, ignored tags and top tags you answered (with score and count).

You can play around with the question order, all you need is to plug in your ordering function:

function calculateWeight(q) {
    return 1 /* your magic ordering goes here */ ;

        available params on q:

            topTags array containing top tags for this user eg: {name: 'tag-name', count: 1, total_score: 1 }
            ignoredTags array of strings 
            interestingTags array of string 


The experimental page lives at: https://stackoverflow.com/new-home

Once you get your magical ordering you can save a preset by clicking the "update" button. This will refresh the page and create a preset (which looks like http://stackoverflow.com?preset=41). You can refresh the page by pressing the refresh button at any time while debugging.

This allows you to do pretty cool things, like this preset by Nick Craver. The page is expensive to download, so there are limits; you may only access it once every 30 seconds.

Can't wait to see what cool presets you come up with! Please post your presets here with an explanation of why you think it is awesome.

Note: this new-home page is experimental, we are not going to keep the same architecture when we go live with the new design. The live design will perform all ordering, server side.

  • Maybe I'm missing something obvious, but where is this? Nov 6, 2010 at 9:04
  • Oh, I found it in the Nick Craver link: stackoverflow.com/new-home Nov 6, 2010 at 9:06
  • @Michael , thanks updated the post
    – waffles
    Nov 6, 2010 at 9:08
  • My plan of return q.user_id == 309308 ? Number.MAX_VALUE : Number.MIN_VALUE was foiled when I realized user_id isn't available :( Nov 6, 2010 at 9:40
  • Updated the link to that preset...38 had a hover issues that 39 resolves :) Nov 6, 2010 at 9:52
  • @Michael userid is in the page, in the header
    – waffles
    Nov 6, 2010 at 10:06
  • I still don't understand what get_score exactly returns... I get 80 for Python and 8 for C, all the rest (ignored and unignored tags alike, tags where I have upvotes for etc.) gives 0.
    – badp
    Nov 6, 2010 at 11:40
  • 1
    @radp it actually is a bit buggy, it works well for @Nick but less for the rest of us, it pushes questions that are in your top scored tags to the top of the list.
    – waffles
    Nov 6, 2010 at 11:42
  • As for me, has_accepted_answer must not have weight at all, because often bad answer is accepted before good appears (because questioner was too hurrying and guy with much better answer just was not quick enough). Sometimes accepted answer has score below zero, you know... Questions with accepted answers must not be far from top also because answer can be just useful/interesting for SO user.
    – Nakilon
    Nov 9, 2010 at 12:09
  • 1
    I must miss something, but this feature is both too cool and too personnal not to become, soon or late, an element of each user configuration, and as such require both config page and an efficicent enough algorithm to be moddable, no ?
    – Riduidel
    Nov 9, 2010 at 12:45
  • @Nakilon That's why I personally avoided mucking around with penalties and bonuses too much :)
    – badp
    Nov 9, 2010 at 20:14

4 Answers 4


Lucky Three design

Pull three interesting, fresh questions at the top. Keep the rest as is. Excerpt:

lucky_three_slots = 3

function calculateWeight(q) {
    interestingness = is_question_interesting(q)
    if(interestingness === interesting_question &&
       q.total_answer_score <= 3 &&   //allow a few upvotes
       q.answer_count <= 3){          //bad question get more answers than votes.
        lucky_three_slots -= 1;       //take the slot
        return -lucky_three_slots;    //clamp to the top
      }                         //For an implementation detail, this function
  }                             //gets called on newest questions first, so the
  //otherwise, default sort     //lucky three questions happen to be sorted by
  return q.last_activity_delta; //time. This is cool, but still a side effect.
  • 1
    it actually does take care of accepted answers, but the interesting question stuff is missing (though you could hack it in with some js foo :)
    – waffles
    Nov 6, 2010 at 11:45

Adjusted freshness

My original idea, discussed at length here. Given the larger body of questions available, I've reduced the bonus factor.

function calculateWeight(q) {
  return q.last_activity_delta / Math.pow(bonus, get_interestingness_of(q));

Variant without the exponential growth

This variant applies the bonus for interesting/ignored tags only once. To balance, the bonus is heftier.

  • I like this one. However, this gives questions with a lot of interesting tags too much weight imho. In my case, a question with java+jsp+jsf+jstl+javabeans (first 4 are in my interesting tags) of about 1 hour old keeps sticking at top. I would set the max to 2 top tags I think, or at least take the last activity time into the weight.
    – user138231
    Nov 8, 2010 at 2:27
  • @BalusC: The last activity time is taken in consideration, it's q.last_activity_delta. Yeah, I admit I didn't think about a situation where there are four interesting tags at any rate.
    – badp
    Nov 8, 2010 at 6:49
  • My concern here is that all questions are in the last 20 minutes or so ...
    – waffles
    Nov 8, 2010 at 11:52
  • @waffles [status-norepro], but I added a variant with a stronger bonus.
    – badp
    Nov 8, 2010 at 12:09
  • @BalusC I've made a variant that only applies the bonus once :)
    – badp
    Nov 8, 2010 at 12:09

Somebody ... added a debugging weight column, so I would be crazy not to share this.


I added a bit of randomness to the mix so a few random questions show up in the list on every load.

function calculateWeight(q) {

    var score = getScore(q.tags); 

    q.weight = q.last_activity_delta / 15
         + (q.has_accepted_answer ? 100000 : 0)
         - (score || -1000)
         + Math.abs(q.total_answer_score) * 4000
         + q.answer_count * 100
         + q.views * 30
         - q.score * 500
         + (q.is_closed ? 100000 : 0);

    // give a random bonus to 1 / 10 questions in the last hour
    if (q.last_activity_delta < 60 * 60 && !q.has_accepted_answer && score == 0) 
       if (Math.floor(Math.random()*5) < 1)
         q.weight = q.weight - (q.views < 10 ? 2500 : 1500); 

    return q.weight;
  • Would it be possible to highlight interesting questions in the review? (And dim/hide ignored questions)
    – jjnguy
    Nov 9, 2010 at 3:17
  • @jjnguy, sure you a little bit of jquery could do that ...
    – waffles
    Nov 9, 2010 at 3:29
  • so you are telling me I should learn Javascript AND JQuery...That is a tall order to fill.
    – jjnguy
    Nov 9, 2010 at 3:31
  • Oh, I c wat u did there
    – jjnguy
    Nov 9, 2010 at 3:33
  • just for reference... I only see negative scores... is it just me?
    – Agos
    Nov 9, 2010 at 16:03

I suggest this order by clause in SQL Server's SELECT statement:

order by score / (views + 1) desc, creation_date_delta desc


  1. score is good. That's why rating is proportional to the score.

  2. Views give change to get score. So if question got many views, but got no score -- that question is not really popular. That's why rating is inversely proportional to views.

  3. I used "+ 1" in order to avoid division by zero. It also gives some advantage to questions with high score and high views versus questions with low score and low views. "+ 1" could be replaced with "+ 100" or something like that.

  4. Order questions that got no score by age: youngest first. That's why "creation_date_delta desc". However I'm not sure what "_delta" means. If it's a timespan between today and creation_date -- then the sorting should be ASCending.

Alternative to "score / (views + 1) desc" It can be replaced with "square(score) / (views + 1) desc" That way high traffic questions would bubble up.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .