             log = v
         if @state.search
             log = (x for x in log when x.search.indexOf(@state.search) != -1)
+        page = @state.page
+        num_pages = Math.ceil(log.length / PAGE_SIZE)
+        log = log.slice(PAGE_SIZE*page, PAGE_SIZE*(page+1))
         @_log = log
 
         <Panel head="Project activity log">
             <Row>
-                <Col sm=6>
+                <Col sm=4>
                     <LogSearch do_search={@do_search} do_select_first={@do_select_first} />
+                </Col>
+                <Col sm=4>
+                    <ButtonGroup>
+                        <Button onClick={@previous_page} disabled={page<=0} >
+                            <Icon name="angle-double-left" /> Newer
+                        </Button>
+                        <Button onClick={@next_page} disabled={page>=num_pages-1} >
+                            <Icon name="angle-double-right" /> Older
+                        </Button>
+                    </ButtonGroup>
                 </Col>
             </Row>
             <Row>

    shouldComponentUpdate: (nextProps, nextState) ->
        if @state.search != nextState.search
            return true
        if not @props.project_log or not nextProps.project_log?
            return true
        if not @props.user_map or not nextProps.user_map?
            return true
        return not nextProps.project_log.equals(@props.project_log) or not nextProps.user_map.equals(@props.user_map)

    render : ->
        # compute visible log entries to render, based on page, search, filters, etc.

        project_id  : rtypes.string.isRequired

    getInitialState: ->
        search : ''   # search that user has requested
        page   : 0

    do_search: (search) ->
        @setState(search:search.toLowerCase())
