         </Grid>
 
 
-
+ProjectController = rclass
+    getDefaultProps: ->
+        project_map : undefined    # an array of projects (or undefined = loading...)
+
+    componentWillReceiveProps: (props) ->
+        @update_project_list(props.project_map)
+
+    update_project_list: (project_map) ->
+        @project_list = (project for project_id, project of project_map)
+        for p in @project_list
+            p.hashtags = parse_project_tags(p)
+            # also search string
+            # and only do this to the projects that change -- use immutable js to know
+        @project_list.sort (p0, p1) -> -misc.cmp(p0.last_edited, p1.last_edited)
+
+    render: ->
+        if not @props.project_map?
+            # TODO
+            return <div>Loading...</div>
+        else
+            if not @project_list?
+                @update_project_list(@props.project_map)
+            return <ProjectSelector project_list={@project_list} />
 
 ProjectsPage = rclass
     render: ->
         <FluxComponent flux={flux} connectToStores = {'projects'}>
-            <ProjectSelector />
+            <ProjectController />
         </FluxComponent>
 
 React.render(<ProjectsPage />, document.getElementById("projects"))

        return 'projects'

    _change: (table, keys) =>
        # TODO: project_list is NOT a list!
        v = []
        for project_id, project of table.get(keys).toJS()
            if project?
                project.hashtags = parse_project_tags(project)
                v.push(project)
            else
                @flux.getActions('projects').delete_project(project_id)
        @flux.getActions('projects').set_projects(v)

flux.createTable('projects', ProjectsTable)


exports.open_project = open_project = (opts) ->
    opts = defaults opts,



    render: ->
        <Grid fluid className="constrained">
            <Well style={marginTop:'1em'}>
                <Row>
