diff --git a/scipost/forms.py b/scipost/forms.py
index 2f22a11e05e4c50f400ce27b2ec85b52c7a21621..980520f5e310b996e0ae816f1275c4aa9af86613 100644
--- a/scipost/forms.py
+++ b/scipost/forms.py
@@ -137,3 +137,20 @@ class CreateGraphForm(forms.ModelForm):
         self.fields['teams_with_access'] = forms.ModelMultipleChoiceField(
             queryset=Team.objects.filter(Q(leader=contributor) | Q(members__in=[contributor])))
         self.fields['teams_with_access'].widget.attrs.update({'placeholder': 'Team to be given access rights:'})
+
+
+class CreateNodeForm(forms.ModelForm):
+    arcs_out = forms.ModelMultipleChoiceField(Node, required=False)
+    class Meta:
+        model = Node
+        fields = ['name', 'description', 'annotation', 'arcs_in', 'arcs_out']
+
+    def __init__(self, *args, **kwargs):
+        graph = kwargs.pop('graph')
+        super(CreateNodeForm, self).__init__(*args, **kwargs)
+        self.fields['arcs_in'] = forms.ModelMultipleChoiceField( 
+            queryset=Node.objects.filter(graph=graph))
+        self.fields['arcs_in'].required=False
+        self.fields['arcs_out'] = forms.ModelMultipleChoiceField(
+            queryset=Node.objects.filter(graph=graph))
+        self.fields['arcs_out'].required=False
diff --git a/scipost/models.py b/scipost/models.py
index 18b7cec94a27eee579a1b2f9574ea7d73b93c733..622b92025e9342cfd9af739abce29d3c79983dbc 100644
--- a/scipost/models.py
+++ b/scipost/models.py
@@ -330,7 +330,7 @@ class Node(models.Model):
     added_by = models.ForeignKey(Contributor, default=None)
     created = models.DateTimeField(default=timezone.now)
     name = models.CharField(max_length=100)
-    arcs_in = models.ManyToManyField('self', blank=True, related_name='node_arcs_in') # arcs pointing into this node
+    arcs_in = models.ManyToManyField('self', blank=True, related_name='node_arcs_in', symmetrical=False) # arcs from another node pointing into this node
     description = models.TextField(blank=True, null=True)
     submissions = models.ManyToManyField('submissions.Submission', blank=True, related_name='node_submissions')
     commentaries = models.ManyToManyField('commentaries.Commentary', blank=True, related_name='node_commentaries')
@@ -338,6 +338,23 @@ class Node(models.Model):
     annotation = models.TextField(blank=True, null=True)
 
     def __str__(self):
-        return self.graph.title[:20] + ': ' + self.name[:20] + ' (owner: ' + self.owner.user.first_name + ' ' + self.owner.user.last_name + ')'
+        return self.graph.title[:20] + ': ' + self.name[:20] 
 
-    
+    def header_as_p(self):
+        context = Context({'graph_id': self.graph.id, 'id': self.id, 'name': self.name})
+        output = '<p><a href="{% url \'scipost:graph\' graph_id=graph_id node_id=id %}">{{ name }}</a></p>'
+        template = Template(output)
+        return template.render(context)
+
+    def contents(self):
+        context = Context({'graph_id': self.graph.id, 'id': self.id, 'name': self.name, 
+                           'description': self.description, 'annotation': self.annotation})
+        output = '''<h3><a href="{% url 'scipost:graph' graph_id=graph_id node_id=id %}">{{ name }}</a></h3>
+                 <p>{{ description }}</p><p>{{ annotation }}</p>'''
+        template = Template(output)
+        return template.render(context)
+
+    def contents_small(self):
+        output = '<div style="font-size: 60%">' + self.contents + '</div>'
+        template = Template(output)
+        return template.render()
diff --git a/scipost/templates/scipost/add_graph_node.html b/scipost/templates/scipost/add_graph_node.html
new file mode 100644
index 0000000000000000000000000000000000000000..785f9ab509a81d2c2f254d611a4409db1a6fbf37
--- /dev/null
+++ b/scipost/templates/scipost/add_graph_node.html
@@ -0,0 +1,20 @@
+{% extends 'scipost/base.html' %}
+
+{% block pagetitle %}: add graph node{% endblock pagetitle %}
+
+{% block bodysup %}
+
+<section>
+  <h1>Add Node to Graph</h1>
+
+  <form action="{% url 'scipost:add_graph_node' graph_id=graph.id %}" method="post">
+    {% csrf_token %}
+    <table>
+      {{ create_node_form.as_table }}
+    </table>
+    <input type="submit" value="Create Node" />
+  </form>
+
+</section>
+
+{% endblock bodysup %}
diff --git a/scipost/templates/scipost/add_team_member.html b/scipost/templates/scipost/add_team_member.html
index de02025bc93ae13ea7efe374da945eda207eb5e7..a12e2c1540d2eb629d6d3be67c706f22027870c5 100644
--- a/scipost/templates/scipost/add_team_member.html
+++ b/scipost/templates/scipost/add_team_member.html
@@ -24,7 +24,9 @@
   <p>Add a member to the Team:</p>
   <form action="{% url 'scipost:add_team_member' team_id=team.id %}" method="post">
     {% csrf_token %}
-    {{ add_team_member_form }}
+    <table>
+      {{ add_team_member_form.as_table }}
+    </table>
     <input type="submit" value="Search" />
   </form>
   {% endif %}
diff --git a/scipost/templates/scipost/graph.html b/scipost/templates/scipost/graph.html
index 8b14e6e4cacdae6374fe9c9493d7a8985f2cc8f1..f4c4b1517b59b5866e438617505192fb01bcbc90 100644
--- a/scipost/templates/scipost/graph.html
+++ b/scipost/templates/scipost/graph.html
@@ -6,9 +6,32 @@
 
 <section>
   <h1>Graph</h1>
-
   {{ graph.contents }}
 
+  <hr class="hr6"/>
+
+  {% if node.arcs_in.all %}
+  <h3>Pointed to from:</h3>
+  <ul>
+    {% for node_in in node.arcs_in.all %}
+    {{ node_in.header_as_p }}
+    {% endfor %}
+  </ul>
+  {% endif %}
+
+  {{ node.contents }}
+
+  {% if nodes_out %}
+  <h3>Pointing to:</h3>
+  <ul>
+    {% for node_out in nodes_out.all %}
+    {{ node_out.header_as_p }}
+    {% endfor %}
+  </ul>
+  {% endif %}
+
+  <hr class="hr6"/>
+  <h3><a href="{% url 'scipost:add_graph_node' graph_id=node.graph.id %}">Add a Node</a></h3>
 
 </section>
 
diff --git a/scipost/urls.py b/scipost/urls.py
index 299141a0a7688e4f3dc4c91e17e278b5eed68bdd..0868067d6a9e6a5923e2a855095ab6e7806c6205 100644
--- a/scipost/urls.py
+++ b/scipost/urls.py
@@ -68,6 +68,7 @@ urlpatterns = [
 
     # Graphs
     url(r'^create_graph$', views.create_graph, name='create_graph'),
-#    url(r'^add_graph_node/(?P<graph_id>[0-9]+)$', views.add_graph_node, name='add_graph_node'),
+    url(r'^add_graph_node/(?P<graph_id>[0-9]+)$', views.add_graph_node, name='add_graph_node'),
     url(r'^graph/(?P<graph_id>[0-9]+)$', views.graph, name='graph'),
+    url(r'^graph/(?P<graph_id>[0-9]+)/(?P<node_id>[0-9]+)$', views.graph, name='graph'),
 ]
diff --git a/scipost/views.py b/scipost/views.py
index f346e7ddd312064fbb15103fcebca59124917524..56ee93eb2c3a20492b2db9c3b1530f4bf946c773 100644
--- a/scipost/views.py
+++ b/scipost/views.py
@@ -653,15 +653,39 @@ def create_graph(request):
 @permission_required('scipost.can_create_graph', raise_exception=True)
 def graph(request, graph_id, node_id=None):
     graph = get_object_or_404(Graph, pk=graph_id)
-#    if node_id is not None:
-#        node = get_object_or_404(Node, pk=node_id)
-#    base_node = Node.objects.filter(graph=graph, arcs_in=None)
-    context = {'graph': graph}
-    return render(request, 'scipost/graph.html', context)
+    if node_id is not None:
+        node = get_object_or_404(Node, pk=node_id)
+        nodes_out = Node.objects.filter(graph=graph, arcs_in__in=[node])
+        context = {'graph': graph, 'node': node, 'nodes_out': nodes_out}
+        return render(request, 'scipost/graph.html', context)
+    elif Node.objects.filter(graph=graph).exists():
+        node = Node.objects.filter(graph=graph).first()
+        return redirect(reverse('scipost:graph', kwargs={'graph_id': graph.id, 'node_id': node.id}))
+    else:
+        return redirect(reverse('scipost:add_graph_node', kwargs={'graph_id': graph.id}))
 
-@permission_required('scipost.can_create_graph', raise_exception=True)
-def add_node_upstream(request, graph_id, node_id):
-    """ Adds a node upstream from the one at node_id """
-    node = get_object_or_404(Node, pk=node_id)
-    
 
+@permission_required('scipost.can_create_graph', raise_exception=True)
+def add_graph_node(request, graph_id):
+    """ Adds a node """
+    graph = get_object_or_404(Graph, pk=graph_id)
+    if request.method == "POST":
+        create_node_form = CreateNodeForm(request.POST, graph=graph)
+        if create_node_form.is_valid():
+            newnode = Node(graph=graph, 
+                           added_by=request.user.contributor,
+                           created=timezone.now(),
+                           name=create_node_form.cleaned_data['name'],
+                           description=create_node_form.cleaned_data['description'],
+                           annotation=create_node_form.cleaned_data['annotation'])
+            newnode.save() # Need to save first, before addressing attribute in next line
+            newnode.arcs_in = create_node_form.cleaned_data['arcs_in']
+            newnode.save()
+            for outnode in create_node_form.cleaned_data['arcs_out']:
+                outnode.arcs_in.add(newnode)
+                outnode.save()
+            return redirect(reverse('scipost:graph', kwargs={'graph_id': graph.id, 'node_id': newnode.id}))
+    else:
+        create_node_form = CreateNodeForm(graph=graph)
+    context = {'graph': graph, 'create_node_form': create_node_form}
+    return render(request, 'scipost/add_graph_node.html', context)