diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx
new file mode 100644
index 00000000..565a5219
--- /dev/null
+++ b/web/components/bet-panel.tsx
@@ -0,0 +1,52 @@
+import React, { useState } from 'react'
+import { Contract } from '../lib/firebase/contracts'
+import { Col } from './layout/col'
+import { Spacer } from './layout/spacer'
+import { YesNoSelector } from './yes-no-selector'
+
+export function BetPanel(props: { contract: Contract; className?: string }) {
+  const { contract, className } = props
+
+  const [betChoice, setBetChoice] = useState<'YES' | 'NO'>('YES')
+  const [shares, setShares] = useState(0)
+
+  return (
+    
+      Pick outcome
+      
+
+      
+
+      Shares
+      
+         setShares(parseInt(e.target.value) || 0)}
+          onFocus={(e) => e.target.select()}
+        />
+      
+
+      
+
+      Price
+      
+        {shares * (betChoice === 'YES' ? 57 : 43)} points
+      
+
+      
+
+      {shares !== 0 && (
+        
+      )}
+    
+  )
+}
diff --git a/web/components/contract-overview.tsx b/web/components/contract-overview.tsx
new file mode 100644
index 00000000..543aa98a
--- /dev/null
+++ b/web/components/contract-overview.tsx
@@ -0,0 +1,64 @@
+import React from 'react'
+import { Line } from 'react-chartjs-2'
+import {
+  CategoryScale,
+  Chart,
+  LinearScale,
+  PointElement,
+  LineElement,
+  Title,
+  Tooltip,
+  Legend,
+} from 'chart.js'
+import { Contract } from '../lib/firebase/contracts'
+import { Col } from './layout/col'
+import { Row } from './layout/row'
+import { Spacer } from './layout/spacer'
+
+// Auto import doesn't work for some reason...
+// So we manually register ChartJS components instead:
+Chart.register(
+  CategoryScale,
+  LinearScale,
+  PointElement,
+  LineElement,
+  Title,
+  Tooltip,
+  Legend
+)
+const chartData = {
+  labels: Array.from({ length: 0 }, (_, i) => i + 1),
+  datasets: [
+    {
+      label: 'Implied probability',
+      data: [],
+      borderColor: 'rgb(75, 192, 192)',
+    },
+  ],
+}
+
+export const ContractOverview = (props: { contract: Contract }) => {
+  const { contract } = props
+
+  return (
+    
+      {contract.question}
+
+      
+        By {contract.creatorName}
+        •
+        Dec 9
+        •
+        200,000 volume
+      
+
+      
+
+      
+
+      
+
+      {contract.description}
+    
+  )
+}
diff --git a/web/components/layout/col.tsx b/web/components/layout/col.tsx
new file mode 100644
index 00000000..da71f130
--- /dev/null
+++ b/web/components/layout/col.tsx
@@ -0,0 +1,5 @@
+export function Col(props: { children?: any; className?: string }) {
+  const { children, className } = props
+
+  return {children}
+}
diff --git a/web/components/layout/row.tsx b/web/components/layout/row.tsx
new file mode 100644
index 00000000..4faaeb6c
--- /dev/null
+++ b/web/components/layout/row.tsx
@@ -0,0 +1,5 @@
+export function Row(props: { children?: any; className?: string }) {
+  const { children, className } = props
+
+  return {children}
+}
diff --git a/web/components/layout/spacer.tsx b/web/components/layout/spacer.tsx
new file mode 100644
index 00000000..04a9b0d7
--- /dev/null
+++ b/web/components/layout/spacer.tsx
@@ -0,0 +1,8 @@
+export function Spacer(props: { w?: number; h?: number }) {
+  const { w, h } = props
+
+  const width = w === undefined ? undefined : w * 0.25 + 'rem'
+  const height = h === undefined ? undefined : h * 0.25 + 'rem'
+
+  return 
+}
diff --git a/web/components/yes-no-selector.tsx b/web/components/yes-no-selector.tsx
new file mode 100644
index 00000000..632e5b54
--- /dev/null
+++ b/web/components/yes-no-selector.tsx
@@ -0,0 +1,66 @@
+import React from 'react'
+import { Row } from './layout/row'
+
+export function YesNoSelector(props: {
+  selected: 'YES' | 'NO'
+  onSelect: (selected: 'YES' | 'NO') => void
+  yesLabel?: string
+  noLabel?: string
+  className?: string
+}) {
+  const { selected, onSelect, yesLabel, noLabel, className } = props
+
+  return (
+    
+      
+
+      
+    
+  )
+}
+
+function Button(props: {
+  className?: string
+  onClick?: () => void
+  color: 'green' | 'red' | 'deemphasized'
+  hideFocusRing?: boolean
+  children?: any
+}) {
+  const { className, onClick, children, color, hideFocusRing } = props
+
+  return (
+    
+  )
+}
+
+function classNames(...classes: any[]) {
+  return classes.filter(Boolean).join(' ')
+}
diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts
index 42166817..87d49c04 100644
--- a/web/lib/firebase/contracts.ts
+++ b/web/lib/firebase/contracts.ts
@@ -3,7 +3,10 @@ import { db } from './init'
 
 export type Contract = {
   id: string
+  creatorId: string
+  creatorName: string
   question: string
+  description: string
 }
 
 const contractCollection = collection(db, 'contracts')
diff --git a/web/pages/contract/[contractId].tsx b/web/pages/contract/[contractId].tsx
index 4b34715a..610b9959 100644
--- a/web/pages/contract/[contractId].tsx
+++ b/web/pages/contract/[contractId].tsx
@@ -1,27 +1,36 @@
+import React from 'react'
 import { useRouter } from 'next/router'
 import { useContract } from '../../hooks/use-contract'
-import { useUser } from '../../hooks/use-user'
+import { Header } from '../../components/header'
+import { Row } from '../../components/layout/row'
+import { ContractOverview } from '../../components/contract-overview'
+import { BetPanel } from '../../components/bet-panel'
 
 export default function ContractPage() {
-  const user = useUser()
-
   const router = useRouter()
   const { contractId } = router.query as { contractId: string }
 
   const contract = useContract(contractId)
 
   if (contract === 'loading') {
-    return Loading...
+    return 
   }
 
-  if (contract === null) {
+  if (!contract) {
     return Contract not found...
   }
 
   return (
-    
-      
{contract.id}
-      
{contract.question}
+    
   )
 }
diff --git a/web/pages/simulator/index.tsx b/web/pages/simulator/index.tsx
index 6e562bbc..5f57f49d 100644
--- a/web/pages/simulator/index.tsx
+++ b/web/pages/simulator/index.tsx
@@ -199,6 +199,7 @@ function NewBidTable(props: {
               type="number"
               placeholder="0"
               className="input input-bordered"
+              style={{ maxWidth: 100 }}
               value={newBid}
               onChange={(e) => setNewBid(parseInt(e.target.value) || 0)}
               onKeyUp={(e) => {