Single-binary self-hosted market watcher for stocks, ETFs, indexes, and futures: live charts, key stats, fundamentals, SEC filings, and SSE streaming.
axumdockerfinancerustself-hostedsqlitestocksvite
1{% extends "base.html" %}
2{% block title %}Search{% endblock %}
3{% block description %}Search and browse every stock, ETF, index, and future this app tracks.{% endblock %}
4{% block extra_css %}<link rel="stylesheet" href="{{ vite_asset('static_src/search/index.js', 'css') }}">{% endblock %}
5
6{% block main %}
7<div class="wrap">
8 <div class="page-head">
9 <h1>Search</h1>
10 {% if q %}
11 <span class="search-count">{{ result_count }} match{{ '' if result_count == 1 else 'es' }}</span>
12 {% else %}
13 <span class="search-count">{{ result_count }} symbol{{ '' if result_count == 1 else 's' }}</span>
14 {% endif %}
15 </div>
16
17 <form class="searchbar" action="/search" method="get" role="search">
18 <input type="search" name="q" value="{{ q }}" placeholder="Search by ticker or company name"
19 autocomplete="off" autofocus aria-label="Search symbols">
20 {# Keep the active kind filter when the text query is resubmitted. #}
21 <input type="hidden" name="kind" value="{{ kind }}">
22 <button type="submit" class="btn btn--accent">Search</button>
23 </form>
24
25 <div class="kind-filter" role="group" aria-label="Filter by kind">
26 {% for opt in [
27 {"value": "", "label": "All"},
28 {"value": "index", "label": "Indexes"},
29 {"value": "future", "label": "Futures"},
30 {"value": "crypto", "label": "Crypto"},
31 {"value": "etf", "label": "ETFs"},
32 {"value": "stock", "label": "Stocks"}
33 ] %}
34 <a class="kind-pill{% if opt.value == kind %} is-active{% endif %}"
35 {% if opt.value == kind %}aria-current="true"{% endif %}
36 href="/search?q={{ q|urlencode }}{% if opt.value %}&kind={{ opt.value }}{% endif %}">{{ opt.label }}</a>
37 {% endfor %}
38 </div>
39
40 {% if show_add %}
41 <div class="add-panel">
42 <div class="add-panel__text">
43 <p class="add-panel__title">Not tracking <span class="num">{{ add_ticker }}</span> yet</p>
44 <p class="add-panel__sub">Add it, and its quote, deep price history, and (for stocks)
45 SEC fundamentals all sync automatically.</p>
46 </div>
47 <button type="button" class="btn btn--accent" data-add-ticker="{{ add_ticker }}">Add {{ add_ticker }}</button>
48 <p class="add-panel__error" data-role="add-error" hidden></p>
49 </div>
50 {% endif %}
51
52 {% if results %}
53 {% from "includes/macros.html" import ticker_card %}
54 {% if asof %}<p class="results-asof">Prices as of {{ asof|asof }}</p>{% endif %}
55 <div class="ticker-grid search-grid">
56 {% for c in results %}{{ ticker_card(c) }}{% endfor %}
57 </div>
58 {% elif q %}
59 <section class="empty empty--search">
60 <svg viewBox="0 0 64 64" fill="none" aria-hidden="true">
61 <circle cx="27" cy="27" r="18" stroke="currentColor" stroke-width="3.5"/>
62 <line x1="40" y1="40" x2="56" y2="56" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"/>
63 </svg>
64 <h1>No matches for “{{ q }}”</h1>
65 <p>{% if show_add %}Use the button above to start tracking it.{% else %}Try a different ticker or company name.{% endif %}</p>
66 </section>
67 {% else %}
68 <section class="empty">
69 <svg viewBox="0 0 64 64" fill="none" aria-hidden="true">
70 <polyline points="4,44 18,30 28,38 44,14 52,24 60,12" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
71 <circle cx="60" cy="12" r="3.6" fill="currentColor"/>
72 </svg>
73 <h1>The market universe is empty</h1>
74 <p>No symbols are seeded yet. Run <code>make seed</code> to import the curated
75 starter list, or add a symbol by searching for its ticker above.</p>
76 </section>
77 {% endif %}
78</div>
79{% endblock %}
80
81{% block extra_js %}<script type="module" src="{{ vite_asset('static_src/search/index.js') }}"></script>{% endblock %}