{ "author": "Zed A. Shaw", "date": "Dec 30, 2022", "has_image": false, "tag": "Demo", "icon": "rocket", "summary": "A 'long start' guide that makes a single feature that uses the entire stack." } ------ # Long Start Making a Page That Does Everything You should go through the [quick start](/docs/quick-start/) before doing this tutorial. This one takes you from your newly installed `bando` setup and teaches you how to create a massively overcomplicated number guessing game that uses every feature of the system. The game is simple, but we'll tour through the whole framework so you know where everything is and what it does.
Experimental Status I'm trying an idea where the longer guide to this project is written as a series of "challenge lessons", and if you can't solve them or they're too vague, you can dive deeper into in-depth HOWTO Recipes on each section. The idea is this might make this guide more interesting and educational. Take a look at this first draft with only the "challenge mode" sections written, and see how far you get. If you enjoy this style, then as I write the in-depth HOWTO Recipes you can try them to learn more. Also let me know if the sections are too vague, or if they just don't really work for you for some reason.
## The Goal This tutorial will create the most incredibly over-engineered number guessing game in the history of the universe. Nearly every feature we'll be adding to the game is overkill, but keeping the goal simple helps us explore every element of the stack without getting stuck also working on the features of the goal. A number guessing game is simply where we display an input and a prompt to guess a number. Then we tell the user if they get it right or wrong. That's it. We'll then take this "game" to an absurd level by using every feature of the `bando` that we can. The total time to complete the tutorial is anywhere from a few hours to a few days, depending on your experience level, bugs you might encounter in my code, or mistakes you make. ## The Three Core Philosophies There are three important design philosophies which will help you understand how to work with the `bando`: 1. ___Low Friction Progress.___ You shouldn't have to create and manage tons of files just to get started. You will eventually be juggling as many files as you have features, but in the beginning you'll make one file, and lightly edit one other. As you progress you'll add one or two files, and as you work everything mostly keeps working in "fake" ways while you build up your idea. A lot of other things work without configuration, and if there is configuration it's hopefully clear where to find it. Finally, there's many templates in the "Djenterator" that help you write out a stock file you need to get started, and you can easily add your own templates. 2. ___UI First Development.___ When _starting_ a web application it's easier to start with the UI, and then use that to drive the rest of the application. This works better today because the UI tends to change less frequently, is _easier_ to change later, but is more difficult to get right in the beginning. I've found if I spend a lot of time working out the UI, refining it, simplifying it, and determining the data it needs, then all of my backend services fall into place easily. When I go the other direction I'm working in a vacuum that has me crafting useless features the UI won't actually need "just in case." 3. ___Copying is the Easiest Way to Learn___ The `bando` comes with a ton of components not so you can use them blindly, but more so you can _extend_ them, or outright _replace_ them later. You can just grab the stock `Video.svelte` to get your video up, work on your UI, and add what you need to `Video.svelte`. If you keep adding hacks to `Video.svelte` and it's breaking your brain then that's a prime time to rewrite it. This helps you create your vision, but also learn how all of these components and features are created so you're not dependent on anyone. Everyone learns by copying others, and the `bando` promotes copying and rewriting as a first class principle by not hiding any of the code from you. These ideas are different from other frameworks you'll encounter, so you'll have to adapt later when you start picking up other technologies. For example, _many_ web frameworks require you to build almost everything from scratch. Need to show some videos? Time to build your own HLS video plugins. Need authentication? Time to reinvent `bcrypt` password storage all over again. Other frameworks seem to idolize building everything from scratch...except the things they've written already. If you try to rebuild that they say you have "Not Invented Here Syndrome." "Reinventing the Wheel." "Don't look at the man behind the curtain." Other frameworks also seem to be enamored with their byzantine configuration files and require you to lay down 4, 5, or sometimes even 10 or more additional files just to get started. Want to just get that first page up? Tough. You'll need the page, a form, a view, a route, a class in your route, a model, the controller, oh did I mention the controller is also called a view on some places? You also need to mirror a 3-4 levels deep directory structure for...reasons. Even worse is how other frameworks push the idea that all this complexity somehow makes them more "professional" or "grown up" when the truth is it's just more complex, not more professional. PHP doesn't have all this BS, and PHP rakes in trillions of dollars a year at the biggest companies we've ever seen. The `bando` is meant to be educational, so it tries not to overload you with everything all at once. My goal is to _gradually_ introduce each piece so you can focus on learning each piece of the stack. Then when you've learned how most of these things work you should be able to jump over to other frameworks that throw a firehose of information at you right away, or that make you build your own authentication yet again. ## The Flat Directory Structure You should familiarize yourself with the directory structure described in the [Quick Start](/client/#/docs/quick/) before you continue. Here's what each directory contains: * `admin` - This is where the admin control panel lives. * `api` - The JSON api handlers live here. * `bando.js` - This is your main management script. * `bando.ps1` - This is a Windows compatible version of the script. * `build.json` - A build configuration used by the `commands/build.js` command that runs esbuild. * `build.prod.json` - The production build configuration used in the `npm run build` command. * `client` - This is where the main web application lives, and is a dynamic Svelte front-end. * `commands` - The `bando.js` script runs commands out of here. * `coverage` - You won't see this at the start, but if you run the coverage commands then you'll see code coverage output here. * `debug` - Various debugging outputs end up here. * `dev.sqlite3` - SQLite3 is the default database (PostgreSQL coming soon). * `dev.sqlite3-shm` - You'll see this because the SQLite3 database is configured for performance. * `dev.sqlite3-wal` - Same as above. * `emails` - Your email templates and configurations are in here. Edit these to change how you email your users. * `knexfile.cjs` - This is the database configuration using [knex.js](https://knexjs.org/guide/). * `lib` - Various support utilities for are found in here, but are only for _non-browser_ tools. Look in `client/` for admin and client imports. * `media` - If you do videos or audio then this can be a separate directory for media. You need this so you can wipe `public/` at any time. * `migrations` - The `knex.js` migrations. You'll see all that I've made over development so you have many examples. * `node_modules` - Your modules when you run `npm install`. * `nodemon.json` - The `package.json` uses [nodemon](https://nodemon.io) to trigger builds when you change something. [Esbuild](https://esbuild.github.io) handles this for `admin` and `client` code though. * `package-lock.json` - `npm` makes this, and you can search in here to see exact versions of your packages and what depends on what. * `package.json` - This configures the project. Take special node of the `"type": "module"` configuration, which configures node for ES6 style ESM imports. * `public` - This directory should be safe to empty if you need to debug how things are being built. It is constructed from all of the other directories to create the content you would place on your webserver. * `queues` - This directory has queue handlers, which use [Bull](https://github.com/OptimalBits/bull) to offload long running processing. Email sends, Discord bot handling, Paypal notifications, Stripe notifications, and Livestream notifications are handled by these. * `rendered` - This is where the rendered static pages go, and you can look in `rendered/pages/blog` to see an example of using this. * `scripts` - These are mostly scripts and "junk" other modules need, like Svelte's TypeScript configuration script, or PM2 configuration examples. * `secrets` - _NEVER PUT THIS IN GIT_. This is where your secret configuration files go. This will contain Payment keys, Discord keys, and other special configurations you don't want people to get. * `socket` - This contains the [socket.io](https://socket.io) handlers that give easy asynchronous communication with the browser. * `static` - These are static files that need to be copied over to `public/`. It's things like icons, images, browser JavaScript code, etc. * `tests` - Contains the automated [ava](https://github.com/avajs/ava) tests for the application. The majority of them use [Playwright](https://playwright.dev) to run the browser like a user to confirm things are still working. It may seem like there's a lot of directories but that's only because it's a flat structure with very limited nesting. Other frameworks have nearly the same number, they just hide them in deep hierarchies that are difficult to remember and search. Once you have a grip on this then continue with the lesson. ## HOWTO Recipes This tutorial is structured in a very terse quick language meant to get you going, and if nothing bad happens, get something up quickly. The problem is, well, bad things always happen in computers, so that's why each section below will link to larger explanations in the [HOWTO Recipes](docs/howto/) section of the site. If you run into trouble in a section, or you want to diver deeper into that feature of the framework, then use the links at the end of the section to explore more. ## Step 1: The Unstyled Fake UI You should have finished the [Quick Start](/client/#/quick/) so you have a working `bando` starter going. You also created a first test page called `client/pages/Test.svelte` and added it to the `client/routes.js` file. You should now undo that before continuing with a new page, just to make sure you know how it works: 1. Remove `Test.svelte` from the `client/routes.js`. 2. Delete the `client/pages/Test.svelte` file. 3. ctrl-c the app and restart it with `npm run DANGER_ADMIN` just to make sure everything is ready. Once you're sure everything is working you'll make a new page for the number guessing: ```shell ./bando.js djent --template ./static/djenterator/client.svelte --output client/pages/NumberGuess.svelte ``` Then add it to the `client/routes.js` just like you did with `Test.svelte`. I'd put the page at `/number_guess/` to start, so in your browser you should be going to [http://127.0.0.1:5001/client/#/number/](http://127.0.0.1:5001/client/#/number/) to see the initial message. Once it's loading you'll change the `api.mock()` to look like this: ```javascript api.mock({ "/api/number_guess": { "get": [200, {"number": 340, "guesses": 10}], } }); ``` Then update the `onMount` to have this `/api/number_guess` URL: ```javascript const [status, data] = await api.get("/api/number_guess"); ``` This will _pretend_ to work, and later you'll delete this `api.mock()`, but for now it lets you develop the UI without more gear. Read the HOWTO Recipe for More ## Step 2: The Blockstart Fake UI Next, you'll import the `client/components/Blockstart.svelte` component so you can do a quick layout. After watching _many_ designers work I've found that they almost universally start with a big blocky layout, _or_ they dump all the media onto a page and _then_ organize it with a big blocky layout. The `Blockstart.svelte` gives you quick access to some prototyping layout tools with a few simple tags, so you can work entirely in HTML to get your initial design working. Once you have your basic layout you'll create a form for the user to input their guess and then submit it. You can work at this stage until your fake page is doing a simple guess loop. To use `Blockstart.svelte` you wrap what you want to layout with a `` tag and then use the [blockstart](https://learnjsthehardway.com/blockstart/) tags to get your initial layout done. Read the HOWTO Recipe for More ## Step 3: The Styled Fake UI Now that you have your Fake UI mostly laid out it's time to "pull out" the `Blockstart.svelte` and convert it to CSS rules. The best way to do this is this: 1. Create your `` block in your `NumberGuess.svelte`. 2. Pick a tag to convert, and give it a name, then add that name to `