Search Dragon - my search engine web app 🔍🐲
Tags: vue, webdev, javascript, showdev
Published: 2021-06-22 13:51:58

This post is about a simple and fun search engine aggregator tool I created recently. I'm going to talk about how I made it and discuss some of the code.


## Background 🐲

Someone asked me to build a useful and fun search tool.

We had just watched [Wish Dragon](https://www.netflix.com/title/81153694) on Netflix. 

The Chinese dragon imagery inspired the name and design.

I used this as a chance to learn an unfamiliar area of JavaScript - opening tabs. 

Vue seemed like a natural choice for handling events and data in JS. It would look similar if it was built in React instead.


## Web app 🐉

I put it together in a few hours and I am pleased to announce Search Dragon as an online tool you can use. 

### Preview

Do a search:

[![Screenshot](https://github.com/MichaelCurrin/search-dragon/raw/v0.4.0/sample-1.png)](https://michaelcurrin.github.io/search-dragon/)

See the tabs opened:

[![Screenshot 2](https://github.com/MichaelCurrin/search-dragon/raw/v0.4.0/sample-2.png)](https://michaelcurrin.github.io/search-dragon/)

### Website

- https://michaelcurrin.github.io/search-dragon/



## What does it do? 🏮

It aggregates searches from popular search engines, including Google and Yahoo, Bing, DuckDuckGo, and Yandex. If for some reason you care about comparing results from each one or balancing your search without being biased by using just one tool.

The app provides some automation to save you copy and pasting searches in multiple windows. You can enter your search query **once** and then a tab will be opened for each search engine. 

Then you run a new search query, the existing tabs get _reused_.


## What is it built on? ⛩

I use GitHub and GitHub Pages to host most of my websites.

This project was built on JavaScript and the [Vue](https://v3.vuejs.org/) framework. But _without_ using Node or a build step. See my [Vue Frontend Quickstart](https://github.com/MichaelCurrin/vue-frontend-quickstart) for a template and info on how that works.


## How does it work? 🔍

The core of the app is 3 parts:

1. Capture user query in HTML `input` element text box.
2. Create the search URLs for each search engine, based on the user's query.
3. When the user submits, use JavaScript to open each URL in a tab.

### Build the URLs

It was easy to build the query URLs in the web app. 

In [main.js](https://github.com/MichaelCurrin/search-dragon/blob/main/main.js), I set up a base URL and then append a URL-encoded query to it. Something like this:

```javascript
const bingUrl = `${BING_BASE_URL}?q=${q}`;
// https://www.bing.com/search?q=my+search+query
```

Note use of a plus sign for a space. A percent-encoding of `%20` would also work but a plus sign is more readable and seems favored by some websites.

Four of the search engines use `q` as the query parameter. And one of them uses `text`.

### Open the tabs

I used JavaScript's [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) browser function to open multiple tabs for the user. The JS is around _windows_, but fortunately, they do get opened as _tabs_ in the same browser window instead of as new windows.

Here is an example of opening a URL with a given window name, then opening a different URL in the _same_ tab.

```javascript
window.open("https://dev.to", "devTo");

window.open("https://dev.to/michaelcurrin", "devTo");
```

### Listen to submission event

When a visitor clicks the search button, a function is run to open multiple tabs for the user.

When pressing <kbd>Enter</kbd>, then the search is also run.

In Vue, this is set up with an Event Listener like this:

```javascript
@keyup.enter="myFunction"
```

I could have used a "form" approach in HTML and Vue, but the simpler approach I used ended up being fine, especially since there is only one input.


## Repo 🔥

Here is the repo on GitHub:

{% github MichaelCurrin/search-dragon %}

The codebase is simple:

- `index.html` - static content.
- `main.js` - dynamic content based on user interaction and configured data.
- `styles.css` - styling.

No `package.json` or `node_modules`! I used the modern ES Modules approach so that I can do an import in my JS directly from a CDN.

```javascript
import { createApp } from "https://unpkg.com/vue@3.1.1/dist/vue.esm-browser.prod.js";
```

Note on content - I didn't put _all_ the content in `main.js`. If JS is disabled or a search engine crawls my site, it might appear a mostly blank. So the content that can be static HTML is left as static HTML - this improves the user's loading experience and SEO ranking (because crawlers can understand my site better).


## Credits 📷

Photo by <a href="https://unsplash.com/@shimikumi32?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Kumiko SHIMIZU</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>