Skip to content

Commit

Permalink
docs: restructured and wrote core principles docs
Browse files Browse the repository at this point in the history
  • Loading branch information
arctic-hen7 committed Jan 22, 2022
1 parent d8416e2 commit 9ee419e
Show file tree
Hide file tree
Showing 54 changed files with 171 additions and 145 deletions.
103 changes: 52 additions & 51 deletions docs/next/en-US/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,63 @@

- [Introduction](/docs/intro)
- [What is Perseus?](/docs/what-is-perseus)
- [Hello World!](/docs/hello-world)
- [Your Second App](/docs/second-app)
- [Core Principles](/docs/core-principles)
- [Hello World!](/docs/tutorials/hello-world)
- [Your Second App](/docs/tutorials/second-app)

---

# Reference

- [`define_app!`](/docs/define-app)
- [Writing Views](/docs/views)
- [Debugging](/docs/debugging)
- [Templates and Routing](/docs/templates/intro)
- [Modifying the `<head>`](/docs/templates/metadata-modification)
- [Modifying HTTP Headers](/docs/templates/setting-headers)
- [Listening to the Router](/docs/templates/router-state)
- [Error Pages](/docs/error-pages)
- [Static Content](/docs/static-content)
- [Internationalization](/docs/i18n/intro)
- [Defining Translations](/docs/i18n/defining)
- [Using Translations](/docs/i18n/using)
- [Translations Managers](/docs/i18n/translations-managers)
- [Other Translation Engines](/docs/i18n/other-engines)
- [Rendering Strategies](/docs/strategies/intro)
- [Build State](/docs/strategies/build-state)
- [Build Paths](/docs/strategies/build-paths)
- [Request State](/docs/strategies/request-state)
- [Revalidation](/docs/strategies/revalidation)
- [Incremental Generation](/docs/strategies/incremental)
- [State Amalgamation](/docs/strategies/amalgamation)
- [Hydration](/docs/hydration)
- [CLI](/docs/cli)
- [Ejecting](/docs/ejecting)
- [Snooping](/docs/snooping)
- [Testing](/docs/testing/intro)
- [Checkpoints](/docs/testing/checkpoints)
- [Fantoccini Basics](/docs/testing/fantoccini-basics)
- [Manual Testing](/docs/testing/manual)
- [Styling](/docs/styling)
- [Communicating with a Server](/docs/server-communication)
- [Stores](/docs/stores)
- [Static Exporting](/docs/exporting)
- [Plugins](/docs/plugins/intro)
- [Functional Actions](/docs/plugins/functional)
- [Control Actions](/docs/plugins/control)
- [Using Plugins](/docs/plugins/using)
- [The `tinker` Action](/docs/plugins/tinker)
- [Writing Plugins](/docs/plugins/writing)
- [Security Considerations](/docs/plugins/security)
- [Publishing Plugins](/docs/plugins/publishing)
- [Deploying](/docs/deploying/intro)
- [Server Deployment](/docs/deploying/serverful)
- [Serverless Deployment](/docs/deploying/serverless)
- [Optimizing Code Size](/docs/deploying/size)
- [Relative Paths](/docs/deploying/relative-paths)
- [Docker Deployment](/docs/deploying/docker)
- [Migrating from v0.2.x](/docs/updating)
- [Common Pitfalls and Known Bugs](/docs/pitfalls-and-bugs)
- [`define_app!`](/docs/reference/define-app)
- [Writing Views](/docs/reference/views)
- [Debugging](/docs/reference/debugging)
- [Templates and Routing](/docs/reference/templates/intro)
- [Modifying the `<head>`](/docs/reference/templates/metadata-modification)
- [Modifying HTTP Headers](/docs/reference/templates/setting-headers)
- [Listening to the Router](/docs/reference/templates/router-state)
- [Error Pages](/docs/reference/error-pages)
- [Static Content](/docs/reference/static-content)
- [Internationalization](/docs/reference/i18n/intro)
- [Defining Translations](/docs/reference/i18n/defining)
- [Using Translations](/docs/reference/i18n/using)
- [Translations Managers](/docs/reference/i18n/translations-managers)
- [Other Translation Engines](/docs/reference/i18n/other-engines)
- [Rendering Strategies](/docs/reference/strategies/intro)
- [Build State](/docs/reference/strategies/build-state)
- [Build Paths](/docs/reference/strategies/build-paths)
- [Request State](/docs/reference/strategies/request-state)
- [Revalidation](/docs/reference/strategies/revalidation)
- [Incremental Generation](/docs/reference/strategies/incremental)
- [State Amalgamation](/docs/reference/strategies/amalgamation)
- [Hydration](/docs/reference/hydration)
- [CLI](/docs/reference/cli)
- [Ejecting](/docs/reference/ejecting)
- [Snooping](/docs/reference/snooping)
- [Testing](/docs/reference/testing/intro)
- [Checkpoints](/docs/reference/testing/checkpoints)
- [Fantoccini Basics](/docs/reference/testing/fantoccini-basics)
- [Manual Testing](/docs/reference/testing/manual)
- [Styling](/docs/reference/styling)
- [Communicating with a Server](/docs/reference/server-communication)
- [Stores](/docs/reference/stores)
- [Static Exporting](/docs/reference/exporting)
- [Plugins](/docs/reference/plugins/intro)
- [Functional Actions](/docs/reference/plugins/functional)
- [Control Actions](/docs/reference/plugins/control)
- [Using Plugins](/docs/reference/plugins/using)
- [The `tinker` Action](/docs/reference/plugins/tinker)
- [Writing Plugins](/docs/reference/plugins/writing)
- [Security Considerations](/docs/reference/plugins/security)
- [Publishing Plugins](/docs/reference/plugins/publishing)
- [Deploying](/docs/reference/deploying/intro)
- [Server Deployment](/docs/reference/deploying/serverful)
- [Serverless Deployment](/docs/reference/deploying/serverless)
- [Optimizing Code Size](/docs/reference/deploying/size)
- [Relative Paths](/docs/reference/deploying/relative-paths)
- [Docker Deployment](/docs/reference/deploying/docker)
- [Migrating from v0.2.x](/docs/reference/updating)
- [Common Pitfalls and Known Bugs](/docs/reference/pitfalls-and-bugs)

---

Expand Down
24 changes: 24 additions & 0 deletions docs/next/en-US/core-principles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Core Principles

Perseus has two fundamental building blocks that make up its entire approach to app building, and if you understand them, you'll be able build extremely complex interfaces in Perseus that come out as fantastic apps.

1. An app is split into templates, which are split into pages.
2. A page is generated from a template and some state.

The first of these is based on the crucial idea of routing on the web, that everything is split into pages. This will be pretty familiar to most people: websites have different pages that display different content. Perseus extends on this with the idea of *templates*, which can produce pages.

The second fundamental tells us how templates work: they take in state, and they put out pages. **Template + state = page.**

Let's take an example to understand how this works in practice. Let's say you're building a music player app that has a vast library of songs (we'll ignore playlists, artists, etc. to keep things simple). The first step in designing your app is thinking about its structure. It comes fairly quickly that you'll need an index page to show the top songs, an about page to tell people about the platform, and one page for each song. Now, the index and about pages have different structures, but every song page has the same structure, just with different content. This is where templates come in. You would have one template for the index page and another for the about page, and then you'd have a third template for the songs pages. Unlike the other two, this template takes in *state*, which it can use to create many different pages with the same structure.

How we generate and manage that stage is where Perseus really shines. Are all those songs listed in a database available at build-time? Use the [*build state*](:reference/strategies/build-state) strategy. Are there too many to build all at once? Use [*incremental generation*](:reference/strategies/incremental-generation) to build only the most commonly used songs first, and then build the rest on-demand when they're first accessed, caching to make them fast for subsequent users.

Once that state is generated, Perseus will go right ahead and proactively prerender your pages, meaning your users see content the second they load your site.

These ideas are built into Perseus at the core, and generating state for templates to generate pages is the fundamental idea behind Perseus. You'll find similar concepts in popular JavaScript frameworks like NextJS and GatsbyJS. It's Perseus' speed, ergonomics, and what it does from there that sets it apart. Once you've generated some state and you've got all the pages ready for your app, there's still a log of work to be done on this music player app. A given song might be paused or playing, the user might have manually turned off dark mode, autoplaying related songs might be on or off. This is all state, but it's not state that we can handle when we build your app. Traditionally, frameworks would leave you on your own here to work this all out, but Perseus tries to be a little more helpful by automatically making your state reactive. Let's say the state for a single song page includes the properties `name`, `artist`, `album`, `year`, and `paused` (there'd probably be a lot more in reality though!). The first four can be set at build time and forgotten about, but `paused` could be changed at any time. No problem, you can change it once the page is loaded. Just call `.set()` on it and Perseus will not only update it locally, but it will update it in a store global to your app so that, if a user goes back to that song later, it will be preserved (or not, your choice). And what about things like `dark_mode`, state that's relevant to the whole app? Well, Perseus provides inbuilt support for reactive global state that can be interacted with from any page.

Now, if you're familiar with user interface (UI) development, this might all sound familiar to you, it's very similar to the *MVC*, or *model, view, controller* pattern. If you've never heard of this, it's just a way of developing apps in which you hold all the states that your app can possibly be in in a *model* and use that to build a *view*. Then you handle user interaction with a *controller*, which modifies the state, and the *view* updates accordingly. Perseus doesn't force this structure on you, and in fact you can opt out entirely from all this reactive state business if it's not your cup of tea with no problems, because Perseus doesn't use MVC as a *pattern* that you develop in, it uses it as an *architecture* that your code works in. You can use development patterns from 1960 or 2060 if you want, Perseus doesn't mind, it'll just work away in the background and make sure your app's state *just works*.

Perseus also adds a little twist to the usual ideas of app state. If your entire app is represented in its state, then wouldn't it be cool if you could *freeze* that state, save it somewhere, and then boot it back up later to bring your app to exactly where it was before. This is inbuilt into Perseus, and it's still insanely fast. But, if you don't want it, you can turn it off, no problem.

If you like the sound of all that, keep reading, and you'll learn how to build your first Perseus app!
38 changes: 0 additions & 38 deletions docs/next/en-US/plugins/functional.md

This file was deleted.

8 changes: 4 additions & 4 deletions docs/next/en-US/cli.md → docs/next/en-US/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ You can also provide `--no-build` to this command to make it skip building your

### `test`

Exactly the same as `serve`, but runs your app in testing mode, which you can read more about [here](:testing/intro).
Exactly the same as `serve`, but runs your app in testing mode, which you can read more about [here](:reference/testing/intro).

### `export`

Builds and exports your app to a series of purely static files at `.perseus/dist/exported/`. This will only work if your app doesn't use any strategies that can't be run at build time, but if that's the case, then you can easily use Perseus without a server after running this command! You can read more about static exporting [here](:exporting).
Builds and exports your app to a series of purely static files at `.perseus/dist/exported/`. This will only work if your app doesn't use any strategies that can't be run at build time, but if that's the case, then you can easily use Perseus without a server after running this command! You can read more about static exporting [here](:reference/exporting).

### `deploy`

Builds your app for production and places it in `pkg/`. You can then upload that folder to a server of your choosing to deploy your app live! You can (and really should) read more about deployment and the potential problems you may encounter [here](:deploying/intro).
Builds your app for production and places it in `pkg/`. You can then upload that folder to a server of your choosing to deploy your app live! You can (and really should) read more about deployment and the potential problems you may encounter [here](:reference/deploying/intro).

### `clean`

Expand All @@ -38,7 +38,7 @@ See the next section for the details of this command.

## Watching

The Perseus CLI supports watching your local directory for changes when running `perseus serve` or `perseus export` through the `-w/--watch` flag. Adding this will make the CLI spawn another version of itself responsible for running the actual builds, and the original process acts as a supervisor. This approach was chosen due to the complexity of the CLI's multithreaded build system, which makes terminating unfinished builds *extremely* difficult.
The Perseus CLI supports watching your local directory for changes when running `perseus serve` or `perseus export` through the `-w/--watch` flag. Adding this will make the CLI spawn another version of itself responsible for running the actual builds, and the original process acts as a supervisor. This approach was chosen due to the complexity of the CLI's multithreaded build system, which makes terminating unfinished builds _extremely_ difficult.

Notably, the CLI spawns another version of itself as a process group (or `JobObject` on Windows) using the [`command-group`](https://github.com/watchexec/command-group) crate, which allows terminations signals to go to all builder child processes. However, this means that the CLI needs to manually handle termination signals to it to terminate the processes in thr group. This means that, if the CLI terminates improperly (e.g. if you `kill` it), you will very likely end up with build jobs running in the background. Those shouldn't be too problematic, and you probably won't even notice them, but a server process could also be orphaned, which would leave a port occupied. If this happens, use `ps aux | grep perseus` to find the process ID, and then `kill` it by that (e.g. `kill 60850`) on Linux. If possible though, avoiding force-terminating the Perseus CLI.

Expand Down
Loading

0 comments on commit 9ee419e

Please sign in to comment.