From 9ee419eefd6329b94edfd726da0af491346af4e7 Mon Sep 17 00:00:00 2001 From: arctic_hen7 Date: Sat, 22 Jan 2022 15:00:03 +1100 Subject: [PATCH] docs: restructured and wrote core principles docs --- docs/next/en-US/SUMMARY.md | 103 +++++++++--------- docs/next/en-US/core-principles.md | 24 ++++ docs/next/en-US/plugins/functional.md | 38 ------- docs/next/en-US/{ => reference}/cli.md | 8 +- docs/next/en-US/{ => reference}/debugging.md | 2 +- docs/next/en-US/{ => reference}/define-app.md | 2 +- .../en-US/{ => reference}/deploying/docker.md | 4 +- .../en-US/{ => reference}/deploying/intro.md | 8 +- .../deploying/relative-paths.md | 0 .../{ => reference}/deploying/serverful.md | 4 +- .../{ => reference}/deploying/serverless.md | 0 .../en-US/{ => reference}/deploying/size.md | 0 docs/next/en-US/{ => reference}/ejecting.md | 10 +- .../next/en-US/{ => reference}/error-pages.md | 0 docs/next/en-US/{ => reference}/exporting.md | 2 +- docs/next/en-US/{ => reference}/hydration.md | 0 .../en-US/{ => reference}/i18n/defining.md | 0 docs/next/en-US/{ => reference}/i18n/intro.md | 0 .../{ => reference}/i18n/other-engines.md | 0 .../i18n/translations-managers.md | 0 docs/next/en-US/{ => reference}/i18n/using.md | 0 .../{ => reference}/pitfalls-and-bugs.md | 6 +- .../en-US/{ => reference}/plugins/control.md | 10 +- .../en-US/reference/plugins/functional.md | 37 +++++++ .../en-US/{ => reference}/plugins/intro.md | 4 +- .../{ => reference}/plugins/publishing.md | 0 .../en-US/{ => reference}/plugins/security.md | 2 +- .../en-US/{ => reference}/plugins/tinker.md | 2 +- .../en-US/{ => reference}/plugins/using.md | 0 .../en-US/{ => reference}/plugins/writing.md | 14 +-- .../{ => reference}/server-communication.md | 12 +- docs/next/en-US/{ => reference}/snooping.md | 0 .../en-US/{ => reference}/static-content.md | 0 docs/next/en-US/{ => reference}/stores.md | 0 .../strategies/amalgamation.md | 4 +- .../{ => reference}/strategies/build-paths.md | 0 .../{ => reference}/strategies/build-state.md | 2 +- .../{ => reference}/strategies/incremental.md | 2 +- .../en-US/{ => reference}/strategies/intro.md | 0 .../strategies/request-state.md | 4 +- .../strategies/revalidation.md | 0 docs/next/en-US/{ => reference}/styling.md | 6 +- .../en-US/{ => reference}/templates/intro.md | 0 .../templates/metadata-modification.md | 0 .../{ => reference}/templates/router-state.md | 0 .../templates/setting-headers.md | 0 .../{ => reference}/testing/checkpoints.md | 0 .../testing/fantoccini-basics.md | 2 +- .../en-US/{ => reference}/testing/intro.md | 0 .../en-US/{ => reference}/testing/manual.md | 0 docs/next/en-US/{ => reference}/updating.md | 4 +- docs/next/en-US/{ => reference}/views.md | 0 .../next/en-US/{ => tutorials}/hello-world.md | 0 docs/next/en-US/{ => tutorials}/second-app.md | 0 54 files changed, 171 insertions(+), 145 deletions(-) create mode 100644 docs/next/en-US/core-principles.md delete mode 100644 docs/next/en-US/plugins/functional.md rename docs/next/en-US/{ => reference}/cli.md (94%) rename docs/next/en-US/{ => reference}/debugging.md (95%) rename docs/next/en-US/{ => reference}/define-app.md (98%) rename docs/next/en-US/{ => reference}/deploying/docker.md (94%) rename docs/next/en-US/{ => reference}/deploying/intro.md (70%) rename docs/next/en-US/{ => reference}/deploying/relative-paths.md (100%) rename docs/next/en-US/{ => reference}/deploying/serverful.md (78%) rename docs/next/en-US/{ => reference}/deploying/serverless.md (100%) rename docs/next/en-US/{ => reference}/deploying/size.md (100%) rename docs/next/en-US/{ => reference}/ejecting.md (75%) rename docs/next/en-US/{ => reference}/error-pages.md (100%) rename docs/next/en-US/{ => reference}/exporting.md (80%) rename docs/next/en-US/{ => reference}/hydration.md (100%) rename docs/next/en-US/{ => reference}/i18n/defining.md (100%) rename docs/next/en-US/{ => reference}/i18n/intro.md (100%) rename docs/next/en-US/{ => reference}/i18n/other-engines.md (100%) rename docs/next/en-US/{ => reference}/i18n/translations-managers.md (100%) rename docs/next/en-US/{ => reference}/i18n/using.md (100%) rename docs/next/en-US/{ => reference}/pitfalls-and-bugs.md (90%) rename docs/next/en-US/{ => reference}/plugins/control.md (73%) create mode 100644 docs/next/en-US/reference/plugins/functional.md rename docs/next/en-US/{ => reference}/plugins/intro.md (68%) rename docs/next/en-US/{ => reference}/plugins/publishing.md (100%) rename docs/next/en-US/{ => reference}/plugins/security.md (90%) rename docs/next/en-US/{ => reference}/plugins/tinker.md (62%) rename docs/next/en-US/{ => reference}/plugins/using.md (100%) rename docs/next/en-US/{ => reference}/plugins/writing.md (70%) rename docs/next/en-US/{ => reference}/server-communication.md (78%) rename docs/next/en-US/{ => reference}/snooping.md (100%) rename docs/next/en-US/{ => reference}/static-content.md (100%) rename docs/next/en-US/{ => reference}/stores.md (100%) rename docs/next/en-US/{ => reference}/strategies/amalgamation.md (68%) rename docs/next/en-US/{ => reference}/strategies/build-paths.md (100%) rename docs/next/en-US/{ => reference}/strategies/build-state.md (97%) rename docs/next/en-US/{ => reference}/strategies/incremental.md (94%) rename docs/next/en-US/{ => reference}/strategies/intro.md (100%) rename docs/next/en-US/{ => reference}/strategies/request-state.md (90%) rename docs/next/en-US/{ => reference}/strategies/revalidation.md (100%) rename docs/next/en-US/{ => reference}/styling.md (97%) rename docs/next/en-US/{ => reference}/templates/intro.md (100%) rename docs/next/en-US/{ => reference}/templates/metadata-modification.md (100%) rename docs/next/en-US/{ => reference}/templates/router-state.md (100%) rename docs/next/en-US/{ => reference}/templates/setting-headers.md (100%) rename docs/next/en-US/{ => reference}/testing/checkpoints.md (100%) rename docs/next/en-US/{ => reference}/testing/fantoccini-basics.md (93%) rename docs/next/en-US/{ => reference}/testing/intro.md (100%) rename docs/next/en-US/{ => reference}/testing/manual.md (100%) rename docs/next/en-US/{ => reference}/updating.md (95%) rename docs/next/en-US/{ => reference}/views.md (100%) rename docs/next/en-US/{ => tutorials}/hello-world.md (100%) rename docs/next/en-US/{ => tutorials}/second-app.md (100%) diff --git a/docs/next/en-US/SUMMARY.md b/docs/next/en-US/SUMMARY.md index 1317d5d05a..8c04700f25 100644 --- a/docs/next/en-US/SUMMARY.md +++ b/docs/next/en-US/SUMMARY.md @@ -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 ``](/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 ``](/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) --- diff --git a/docs/next/en-US/core-principles.md b/docs/next/en-US/core-principles.md new file mode 100644 index 0000000000..f3bcf89541 --- /dev/null +++ b/docs/next/en-US/core-principles.md @@ -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! diff --git a/docs/next/en-US/plugins/functional.md b/docs/next/en-US/plugins/functional.md deleted file mode 100644 index 61e3799254..0000000000 --- a/docs/next/en-US/plugins/functional.md +++ /dev/null @@ -1,38 +0,0 @@ -# Functional Actions - -The first type of action that a Perseus plugin can take is a functional action, and a single functional action can be taken by many plugins. These are the more common type of Perseus action, and are extremely versatile in extending the capabilities of the Perseus engine. However, they don't have the ability to replace critical functionality on their own. - -## List of Functional Actions - -Here's a list of all the functional actions currently supported by Perseus, which will likely grow over time. You can see these in [this file](https://github.com/arctic-hen7/perseus/blob/main/packages/perseus/src/plugins/functional.rs) in the Perseus repository. - -If you'd like to request that a new action, functional or control, be added, please [open an issue](https://github.com/arctic-hen7/perseus/issues/new/choose). - -- `tinker` -- see [this section](:plugins/tinker) -- `settings_actions` -- actions that can alter the settings provided by the user with [`define_app!`](:define-app) - - `add_static_aliases` -- adds extra static aliases to the user's app (e.g. a [TailwindCSS](https://tailwindcss.com) stylesheet) - - `add_templates` -- adds extra templates to the user's app (e.g. a prebuilt documentation system) - - `add_error_pages` -- adds extra [error pages](:error-pages) to the user's app (e.g. a prebuilt 404 page) -- `build_actions` -- actions that'll be run when the user runs `perseus build` or `perseus serve` as part of the build process (these will not be run in [static exporting](:exporting)) - - `before_build` -- runs arbitrary code just before the build process starts (e.g. to run a CSS preprocessor) - - `after_successful_build` -- runs arbitrary code after the build process has completed, if it was successful (e.g. copying custom files into `.perseus/dist/`) - - `after_failed_build` -- runs arbitrary code after the build process has completed, if it failed (e.g. to report the failed build to a server crash management system) - - `after_failed_global_state_creation` -- runs arbitrary code after if the build process failed to generate global state -- `export_actions` -- actions that'll be run when the user runs `perseus export` - - `before_export` -- runs arbitrary code just before the export process starts (e.g. to run a CSS preprocessor) - - `after_successful_build` -- runs arbitrary code after the build process has completed (inside the export process), if it was successful (e.g. copying custom files into `.perseus/dist/`) - - `after_failed_build` -- runs arbitrary code after the build process has completed (inside the export process), if it failed (e.g. to report the failed export to a server crash management system) - - `after_failed_export` -- runs arbitrary code after the export process has completed, if it failed (e.g. to report the failed export to a server crash management system) - - `after_failed_static_copy` -- runs arbitrary code if the export process fails to copy the `static` directory (e.g. to report the failed export to a server crash management system) - - `after_failed_static_alias_dir_copy` -- runs arbitrary code if the export process fails to copy a static alias that was a directory (e.g. to report the failed export to a server crash management system) - - `after_failed_static_alias_file_copy` -- runs arbitrary code if the export process fails to copy a static alias that was a file (e.g. to report the failed export to a server crash management system) - - `after_successful_export` -- runs arbitrary code after the export process has completed, if it was successful (e.g. copying custom files into `.perseus/dist/`) - - `after_failed_global_state_creation` -- runs arbitrary code if the export process failed to generate global state -- `export_error_page_actions` --- actions that'll be run when exporting an error page - - `before_export_error_page` --- runs arbitrary code before this process has started (providing the error code to be exported for and the output file) - - `after_successful_export_error_page` -- runs arbitrary code after this process has completed, if it was successful - - `after_failed_write` -- runs arbitrary code after this process has completed, if it couldn't write to the target output file -- `server_actions` -- actions that'll be run as part of the Perseus server when the user runs `perseus serve` (or when a [serverful production deployment](:deploying/serverful) runs) - - `before_serve` -- runs arbitrary code before the server starts (e.g. to spawn an API server) -- `client_actions` -- actions that'll run in the browser when the user's app is accessed - - `start` -- runs arbitrary code when the Wasm delivered to the browser is executed (e.g. to ping an analytics service) diff --git a/docs/next/en-US/cli.md b/docs/next/en-US/reference/cli.md similarity index 94% rename from docs/next/en-US/cli.md rename to docs/next/en-US/reference/cli.md index cb37b4126d..7ba8cb7efc 100644 --- a/docs/next/en-US/cli.md +++ b/docs/next/en-US/reference/cli.md @@ -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` @@ -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. diff --git a/docs/next/en-US/debugging.md b/docs/next/en-US/reference/debugging.md similarity index 95% rename from docs/next/en-US/debugging.md rename to docs/next/en-US/reference/debugging.md index 4584df30df..5739b9272f 100644 --- a/docs/next/en-US/debugging.md +++ b/docs/next/en-US/reference/debugging.md @@ -6,4 +6,4 @@ However, Perseus exports a macro called `web_log!` that can be used to print to ## Debugging the build process -If you have a problem in your build process, you'll probably notice quite quickly that you can't see any `dbg!`, `println!`, or `web_log!` calls in your terminal when you run `perseus serve` (or `export`, `build`, etc.). This is because the CLI hides the output of the commands that it runs behind the scenes (if you've ever had the CLI spout an error at you and show you everything it's done behind the scenes, you'll probably understand why!). As useful as this is for simple usability, it can be extremely annoying for loggin, so the CLI provides a separate command `perseus snoop `, which allows you to run one of the commands that the CLI does, directly. Usually, this will be `perseus snoop build`, though you can also use `perseus snoop wasm-build` if you're having an issue in your Wasm building (usually caused by a crate that can't work in the browser), or `perseus snoop serve` if you're getting errors on the server (which shouldn't happen unless you've modified it). To learn more, see [this page](:snooping). +If you have a problem in your build process, you'll probably notice quite quickly that you can't see any `dbg!`, `println!`, or `web_log!` calls in your terminal when you run `perseus serve` (or `export`, `build`, etc.). This is because the CLI hides the output of the commands that it runs behind the scenes (if you've ever had the CLI spout an error at you and show you everything it's done behind the scenes, you'll probably understand why!). As useful as this is for simple usability, it can be extremely annoying for loggin, so the CLI provides a separate command `perseus snoop `, which allows you to run one of the commands that the CLI does, directly. Usually, this will be `perseus snoop build`, though you can also use `perseus snoop wasm-build` if you're having an issue in your Wasm building (usually caused by a crate that can't work in the browser), or `perseus snoop serve` if you're getting errors on the server (which shouldn't happen unless you've modified it). To learn more, see [this page](:reference/snooping). diff --git a/docs/next/en-US/define-app.md b/docs/next/en-US/reference/define-app.md similarity index 98% rename from docs/next/en-US/define-app.md rename to docs/next/en-US/reference/define-app.md index fb948855d1..9c80d43073 100644 --- a/docs/next/en-US/define-app.md +++ b/docs/next/en-US/reference/define-app.md @@ -25,7 +25,7 @@ Here's a list of everything you can provide to the macro and what each one does - `default` -- the default locale of your app (e.g. `en-US`) - `other` -- a list of the other locales your app supports - `static_aliases` (optional) -- a list of aliases to static files in your project (e.g. for a favicon) -- `plugins` (optional) -- a list of plugins to add to extend Perseus (see [here](:plugins/intro)) +- `plugins` (optional) -- a list of plugins to add to extend Perseus (see [here](:reference/plugins/intro)) - `dist_path` (optional) -- a custom path to distribution artifacts (this is relative to `.perseus/`!) - `mutable_store` (optional) -- a custom mutable store - `translations_manager` (optional) -- a custom translations manager diff --git a/docs/next/en-US/deploying/docker.md b/docs/next/en-US/reference/deploying/docker.md similarity index 94% rename from docs/next/en-US/deploying/docker.md rename to docs/next/en-US/reference/deploying/docker.md index ff4d29cac6..817a4cacbf 100644 --- a/docs/next/en-US/deploying/docker.md +++ b/docs/next/en-US/reference/deploying/docker.md @@ -1,10 +1,10 @@ # Docker Deployment -For situations where [serverful deployment](:deploying/serverful) is required, or in case there is a need to deploy one of the examples found on GitHub without prior setup of all necessary dependencies, below are `Dockerfile` examples meant to serve for different deployment scenarios. These steps can also serve as guidelines for production deployments. +For situations where [serverful deployment](:reference/deploying/serverful) is required, or in case there is a need to deploy one of the examples found on GitHub without prior setup of all necessary dependencies, below are `Dockerfile` examples meant to serve for different deployment scenarios. These steps can also serve as guidelines for production deployments. Note that the following examples should be modified for your particular use-case rather than being used as-is. Also, these `Dockerfile`s are standalone because they use `curl` to download examples directly from the Perseus repository (of course, you'll probably want to use your own code in production). -Before proceeding with this section, you should be familiar with Docker's [multi-stage builds system](https://docs.docker.com/develop/develop-images/multistage-build) and Perseus' [code size optimizations](:deploying/size). +Before proceeding with this section, you should be familiar with Docker's [multi-stage builds system](https://docs.docker.com/develop/develop-images/multistage-build) and Perseus' [code size optimizations](:reference/deploying/size).
Production example using the size optimizations plugin diff --git a/docs/next/en-US/deploying/intro.md b/docs/next/en-US/reference/deploying/intro.md similarity index 70% rename from docs/next/en-US/deploying/intro.md rename to docs/next/en-US/reference/deploying/intro.md index ab3011ad70..084c89d5e4 100644 --- a/docs/next/en-US/deploying/intro.md +++ b/docs/next/en-US/reference/deploying/intro.md @@ -1,6 +1,6 @@ # Deploying -> **WARNING:** although Perseus is technically ready for deployment, the system is not yet recommended for production! See [here](:what-is-perseus.md#how-stable-is-it) for more details. +> **WARNING:** although Perseus is technically ready for deployment, the system is not yet recommended for production! See [here](:reference/what-is-perseus.md#how-stable-is-it) for more details. Perseus is a complex system, but we aim to make deploying it as easy as possible. This section will describe a few different types of Perseus deployments, and how they can be managed. @@ -10,15 +10,15 @@ The Perseus CLI supports the `--release` flag on the `build`, `serve`, and `expo ## `perseus deploy` -If you haven't [ejected](:ejecting), then you can prepare your app for deployment with a single command: `perseus deploy`. If you can use [static exporting](:exporting), then you should run `perseus deploy -e`, otherwise you should just use `perseus deploy`. +If you haven't [ejected](:reference/ejecting), then you can prepare your app for deployment with a single command: `perseus deploy`. If you can use [static exporting](:reference/exporting), then you should run `perseus deploy -e`, otherwise you should just use `perseus deploy`. This will create a new directory `pkg/` for you (you can change that by specifying `--output`) which will contain everything you need to deploy your app. That directory is entirely self-contained, and can be copied to an appropriate hosting provider for production deployment! -Note that this command will run a number of optimizations in the background, including using the `--release` flag, but it won't try to aggressively minimize your Wasm code size. For tips on how to do that, see [here](:deploying/size). +Note that this command will run a number of optimizations in the background, including using the `--release` flag, but it won't try to aggressively minimize your Wasm code size. For tips on how to do that, see [here](:reference/deploying/size). ### Static Exporting -If you use `perseus deploy -e`, the contents of `pkg/` can be served by any file host that can handle the [slight hiccup](:exporting#file-extensions) of file extensions. Locally, you can test this out with [`serve`](https://github.com/vercel/serve), a JavaScript package designed for this purpose. +If you use `perseus deploy -e`, the contents of `pkg/` can be served by any file host that can handle the [slight hiccup](:reference/exporting#file-extensions) of file extensions. Locally, you can test this out with [`serve`](https://github.com/vercel/serve), a JavaScript package designed for this purpose. ### Fully-Fledged Server diff --git a/docs/next/en-US/deploying/relative-paths.md b/docs/next/en-US/reference/deploying/relative-paths.md similarity index 100% rename from docs/next/en-US/deploying/relative-paths.md rename to docs/next/en-US/reference/deploying/relative-paths.md diff --git a/docs/next/en-US/deploying/serverful.md b/docs/next/en-US/reference/deploying/serverful.md similarity index 78% rename from docs/next/en-US/deploying/serverful.md rename to docs/next/en-US/reference/deploying/serverful.md index 0dc4115aff..380e842b8b 100644 --- a/docs/next/en-US/deploying/serverful.md +++ b/docs/next/en-US/reference/deploying/serverful.md @@ -6,9 +6,9 @@ You can prepare your production server by running `perseus deploy`, which will c ## Hosting Providers -As you may recall from [this section](:stores) on immutable and mutable stores, Perseus modifies some data at runtime, which is problematic if your hosting provider imposes the restriction that you can't write to the filesystem (as Netlify does). Perseus automatically handles this as well as it can by separating out mutable from immutable data, and storing as much as it can on the filesystem without causing problems. However, data for pages that use the _revalidation_ or _incremental generation_ strategies must be placed in a location where it can be changed while Perseus is running. +As you may recall from [this section](:reference/stores) on immutable and mutable stores, Perseus modifies some data at runtime, which is problematic if your hosting provider imposes the restriction that you can't write to the filesystem (as Netlify does). Perseus automatically handles this as well as it can by separating out mutable from immutable data, and storing as much as it can on the filesystem without causing problems. However, data for pages that use the _revalidation_ or _incremental generation_ strategies must be placed in a location where it can be changed while Perseus is running. -If you're only using _build state_ and/or _build paths_ (or neither), you should export your app to purely static files instead, which you can read more about doing [here](:exporting). That will avoid this entire category of problems, and you can deploy basically wherever you want. +If you're only using _build state_ and/or _build paths_ (or neither), you should export your app to purely static files instead, which you can read more about doing [here](:reference/exporting). That will avoid this entire category of problems, and you can deploy basically wherever you want. If you're bringing _request state_ into the mix, you can't export to static files, but you can run on a read-only filesystem, because only the _revalidation_ and _incremental generation_ strategies require mutability. Perseus will use a mutable store on the filesystem in the background, but won't ever need it. diff --git a/docs/next/en-US/deploying/serverless.md b/docs/next/en-US/reference/deploying/serverless.md similarity index 100% rename from docs/next/en-US/deploying/serverless.md rename to docs/next/en-US/reference/deploying/serverless.md diff --git a/docs/next/en-US/deploying/size.md b/docs/next/en-US/reference/deploying/size.md similarity index 100% rename from docs/next/en-US/deploying/size.md rename to docs/next/en-US/reference/deploying/size.md diff --git a/docs/next/en-US/ejecting.md b/docs/next/en-US/reference/ejecting.md similarity index 75% rename from docs/next/en-US/ejecting.md rename to docs/next/en-US/reference/ejecting.md index c9b47419bd..8721b84c5d 100644 --- a/docs/next/en-US/ejecting.md +++ b/docs/next/en-US/reference/ejecting.md @@ -4,9 +4,9 @@ The Perseus CLI is fantastic at enabling rapid and efficient development, but so However, there are some things that are too advanced for the CLI to support, and, in those cases, you'll need to eject. Don't worry, you'll still be able to use the CLI itself for running your app, but you'll be given access to the engine that underlies it, and you'll be able to tweak basically anything you want. -Before you proceed though, you should know that Perseus supports modularizing the functionality of ejected code through [plugins](:plugins/intro), which let you modify the `.perseus/` directory in all sorts of ways (including arbitrary file modification), without needing to eject in the first place. In nearly all cases (even for smaller apps), plugins are a better way to go than ejecting. In future, you'll even be able to replace the entire `.perseus/` directory with a custom engine (planned for v0.4.0)! +Before you proceed though, you should know that Perseus supports modularizing the functionality of ejected code through [plugins](:reference/plugins/intro), which let you modify the `.perseus/` directory in all sorts of ways (including arbitrary file modification), without needing to eject in the first place. In nearly all cases (even for smaller apps), plugins are a better way to go than ejecting. In future, you'll even be able to replace the entire `.perseus/` directory with a custom engine (planned for v0.4.0)! -*Note: ejecting from Perseus exposes the bones of the system, and you should be quite familiar with Rust before doing this. That said, if you're just doing it for fun, go right ahead!* +_Note: ejecting from Perseus exposes the bones of the system, and you should be quite familiar with Rust before doing this. That said, if you're just doing it for fun, go right ahead!_ ## Ejecting @@ -16,8 +16,8 @@ This command does two things: it removes `.perseus/` from your `.gitignore` file After ejecting, there are a few things that change. -- You can no longer run `perseus clean` unless you provide the `--dist` flag (otherwise it would delete the engine you're tweaking!) -- A ton of files appear in Git that you should commit, all from `.perseus/` +- You can no longer run `perseus clean` unless you provide the `--dist` flag (otherwise it would delete the engine you're tweaking!) +- A ton of files appear in Git that you should commit, all from `.perseus/` ## Architecture @@ -25,7 +25,7 @@ Under the hood, Perseus' CLI is only responsible for running commands like `carg One of the first things you'll probably want to do if you choose to eject is to remove the `[workspace]` declaration from `.perseus/Cargo.toml` and instead add both crates inside to your project's workspace. This will make sure that linters like RLS will check your modifications to `.perseus/` for any problems, and you won't be flying blind. -The rest of the documentation on how Perseus works under the hood can be found in the *Advanced* section of the book, which you'll want to peruse if you choose to eject. +The rest of the documentation on how Perseus works under the hood can be found in the _Advanced_ section of the book, which you'll want to peruse if you choose to eject. ## Reversing Ejection diff --git a/docs/next/en-US/error-pages.md b/docs/next/en-US/reference/error-pages.md similarity index 100% rename from docs/next/en-US/error-pages.md rename to docs/next/en-US/reference/error-pages.md diff --git a/docs/next/en-US/exporting.md b/docs/next/en-US/reference/exporting.md similarity index 80% rename from docs/next/en-US/exporting.md rename to docs/next/en-US/reference/exporting.md index 8da68e1d43..9dbba18948 100644 --- a/docs/next/en-US/exporting.md +++ b/docs/next/en-US/reference/exporting.md @@ -2,7 +2,7 @@ Thus far, we've used `perseus serve` to build and serve Perseus apps, but there is an alternative way that offers better performance in some cases. Namely, if your app doesn't need any rendering strategies that can't be run at build time (so if you're only using _build state_ and/or _build paths_ or neither), you can export your app to a set of purely static files that can be served by almost any hosting provider. You can do this by running `perseus export`, which will create a new directory `.perseus/dist/exported/`, the contents of which can be served on a system like [GitHub Pages](https:://pages.github.com). Your app should behave in the exact same way with exporting as with normal serving. If this isn't the case, please [open an issue](https://github.com/arctic-hen7/perseus/issues/new/choose). -There is only one known difference between the behavior of your exported site and your normally served site, and that's regarding [static aliases](:static-content). In a normal serving scenario, any static aliases that conflicted with a Perseus page or internal asset would be ignored, but, in an exporting context, **any static aliases that conflict with Perseus pages will override them**! If you suspect this might be happening to you, try exporting without those aliases and make sure the URL of your alias file doesn't already exist (in which case it would be a Perseus component). +There is only one known difference between the behavior of your exported site and your normally served site, and that's regarding [static aliases](:reference/static-content). In a normal serving scenario, any static aliases that conflicted with a Perseus page or internal asset would be ignored, but, in an exporting context, **any static aliases that conflict with Perseus pages will override them**! If you suspect this might be happening to you, try exporting without those aliases and make sure the URL of your alias file doesn't already exist (in which case it would be a Perseus component). ## File Extensions diff --git a/docs/next/en-US/hydration.md b/docs/next/en-US/reference/hydration.md similarity index 100% rename from docs/next/en-US/hydration.md rename to docs/next/en-US/reference/hydration.md diff --git a/docs/next/en-US/i18n/defining.md b/docs/next/en-US/reference/i18n/defining.md similarity index 100% rename from docs/next/en-US/i18n/defining.md rename to docs/next/en-US/reference/i18n/defining.md diff --git a/docs/next/en-US/i18n/intro.md b/docs/next/en-US/reference/i18n/intro.md similarity index 100% rename from docs/next/en-US/i18n/intro.md rename to docs/next/en-US/reference/i18n/intro.md diff --git a/docs/next/en-US/i18n/other-engines.md b/docs/next/en-US/reference/i18n/other-engines.md similarity index 100% rename from docs/next/en-US/i18n/other-engines.md rename to docs/next/en-US/reference/i18n/other-engines.md diff --git a/docs/next/en-US/i18n/translations-managers.md b/docs/next/en-US/reference/i18n/translations-managers.md similarity index 100% rename from docs/next/en-US/i18n/translations-managers.md rename to docs/next/en-US/reference/i18n/translations-managers.md diff --git a/docs/next/en-US/i18n/using.md b/docs/next/en-US/reference/i18n/using.md similarity index 100% rename from docs/next/en-US/i18n/using.md rename to docs/next/en-US/reference/i18n/using.md diff --git a/docs/next/en-US/pitfalls-and-bugs.md b/docs/next/en-US/reference/pitfalls-and-bugs.md similarity index 90% rename from docs/next/en-US/pitfalls-and-bugs.md rename to docs/next/en-US/reference/pitfalls-and-bugs.md index 0eca66da0d..000fec64a1 100644 --- a/docs/next/en-US/pitfalls-and-bugs.md +++ b/docs/next/en-US/reference/pitfalls-and-bugs.md @@ -8,7 +8,7 @@ If you're running Arch Linux or a derivative (e.g. Manjaro), you're very likely ## I'm getting JSON error messages... -If an error occurs during `perseus serve`, it's very possible that you'll get error messages in JSON, which are utterly unreadable. This is because of the way the server is run, the Perseus CLI needs a JSON output so that it can figure out where the server binary is. You can access the human-readable logs by [snooping](:snooping) on the output though, which you can do by running `perseus snoop serve` (but make sure you've run `perseus build` first). +If an error occurs during `perseus serve`, it's very possible that you'll get error messages in JSON, which are utterly unreadable. This is because of the way the server is run, the Perseus CLI needs a JSON output so that it can figure out where the server binary is. You can access the human-readable logs by [snooping](:reference/snooping) on the output though, which you can do by running `perseus snoop serve` (but make sure you've run `perseus build` first). ## Perseus doesn't work on an M1 Mac @@ -23,7 +23,7 @@ This will disable optimizations for your Wasm bundle, which prevents this issue ## I want to apply X to my `Cargo.toml`, but it doesn't work -Perseus has a rather unique code structure that will foil most attempts at modifying your own `Cargo.toml`. For example, if you wanted to change the `codegen_units` in the release profile of your app, you couldn't do this in your own `Cargo.toml`, it would have no effect. The reason for this is that the code your write is actually a library that's imported by the CLI's engines, so any custom configuration has to be made directly on the engines. In other words, you'll need to apply your changes on `.perseus/Cargo.toml` instead. You can also apply customizations on the server and the builder, which are separate crates under `.perseus/`. Note that modifying `.perseus/` and retaining your changes requires [ejecting](:ejecting), or you could [write a plugin](:plugins/writing) if it's a change you make a lot. +Perseus has a rather unique code structure that will foil most attempts at modifying your own `Cargo.toml`. For example, if you wanted to change the `codegen_units` in the release profile of your app, you couldn't do this in your own `Cargo.toml`, it would have no effect. The reason for this is that the code your write is actually a library that's imported by the CLI's engines, so any custom configuration has to be made directly on the engines. In other words, you'll need to apply your changes on `.perseus/Cargo.toml` instead. You can also apply customizations on the server and the builder, which are separate crates under `.perseus/`. Note that modifying `.perseus/` and retaining your changes requires [ejecting](:reference/ejecting), or you could [write a plugin](:reference/plugins/writing) if it's a change you make a lot. ## Cargo is putting out strange errors... @@ -42,4 +42,4 @@ That will archive the `git/` and `registry/` folders in `~/.cargo/`, which shoul ## I want to disable a Perseus default feature, but it's not doing anything -If you add `default-features = false` to your `Cargo.toml` and expect Perseus to adapt accordingly, you're in for a bit of a shock unfortunately! The reason for this is that the Perseus CLI isn't (yet) smart enough to know you've done this, so it will completely ignore you and press on with default features in the engine, and those settings will override your own. To disable default features, you'll need to also make these changes in `.perseus/Cargo.toml`, `.perseus/builder/Cargo.toml`, and `.perseus/server/Cargo.toml` (and you'll need to [eject](:ejecting) to save your changes). In future versions, the CLI will be able to detect your preferences for this and update accordingly. +If you add `default-features = false` to your `Cargo.toml` and expect Perseus to adapt accordingly, you're in for a bit of a shock unfortunately! The reason for this is that the Perseus CLI isn't (yet) smart enough to know you've done this, so it will completely ignore you and press on with default features in the engine, and those settings will override your own. To disable default features, you'll need to also make these changes in `.perseus/Cargo.toml`, `.perseus/builder/Cargo.toml`, and `.perseus/server/Cargo.toml` (and you'll need to [eject](:reference/ejecting) to save your changes). In future versions, the CLI will be able to detect your preferences for this and update accordingly. diff --git a/docs/next/en-US/plugins/control.md b/docs/next/en-US/reference/plugins/control.md similarity index 73% rename from docs/next/en-US/plugins/control.md rename to docs/next/en-US/reference/plugins/control.md index 365cb0c053..1736164859 100644 --- a/docs/next/en-US/plugins/control.md +++ b/docs/next/en-US/reference/plugins/control.md @@ -1,6 +1,6 @@ # Control Actions -Control actions in Perseus can only be taken by one plugin, unlike [functional actions](:plugins/functional), because, if multiple plugins took them, Perseus wouldn't know what to do. For example, if more than one plugin tried to replace the [immutable store](:stores), Perseus wouldn't know which alternative to use. +Control actions in Perseus can only be taken by one plugin, unlike [functional actions](:reference/plugins/functional), because, if multiple plugins took them, Perseus wouldn't know what to do. For example, if more than one plugin tried to replace the [immutable store](:reference/stores), Perseus wouldn't know which alternative to use. Control actions can be considered more powerful than functional actions because they allow a plugin to not only extend, but to replace engine functionality. @@ -12,11 +12,11 @@ If you'd like to request that a new action, functional or control, be added, ple _Note: there are currently very few control actions, and this list will be expanded over time._ -- `settings_actions` -- actions that can alter the settings provided by the user with [`define_app!`](:define-app) - - `set_immutable_store` -- sets an alternative [immutable store](:stores) (e.g. to store data somewhere other than the filesystem for some reason) +- `settings_actions` -- actions that can alter the settings provided by the user with [`define_app!`](:reference/define-app) + - `set_immutable_store` -- sets an alternative [immutable store](:reference/stores) (e.g. to store data somewhere other than the filesystem for some reason) - `set_locales` -- sets the app's locales (e.g. to fetch locales from a database in a more convenient way) - `set_app_root` -- sets the HTML `id` of the `div` in which to render Perseus (e.g. to fetch the app root from some other service) -- `build_actions` -- actions that'll be run when the user runs `perseus build` or `perseus serve` as part of the build process (these will not be run in [static exporting](:exporting)) +- `build_actions` -- actions that'll be run when the user runs `perseus build` or `perseus serve` as part of the build process (these will not be run in [static exporting](:reference/exporting)) - `export_actions` -- actions that'll be run when the user runs `perseus export` -- `server_actions` -- actions that'll be run as part of the Perseus server when the user runs `perseus serve` (or when a [serverful production deployment](:deploying/serverful) runs) +- `server_actions` -- actions that'll be run as part of the Perseus server when the user runs `perseus serve` (or when a [serverful production deployment](:reference/deploying/serverful) runs) - `client_actions` -- actions that'll run in the browser when the user's app is accessed diff --git a/docs/next/en-US/reference/plugins/functional.md b/docs/next/en-US/reference/plugins/functional.md new file mode 100644 index 0000000000..317b77959e --- /dev/null +++ b/docs/next/en-US/reference/plugins/functional.md @@ -0,0 +1,37 @@ +# Functional Actions + +The first type of action that a Perseus plugin can take is a functional action, and a single functional action can be taken by many plugins. These are the more common type of Perseus action, and are extremely versatile in extending the capabilities of the Perseus engine. However, they don't have the ability to replace critical functionality on their own. + +## List of Functional Actions + +Here's a list of all the functional actions currently supported by Perseus, which will likely grow over time. You can see these in [this file](https://github.com/arctic-hen7/perseus/blob/main/packages/perseus/src/plugins/functional.rs) in the Perseus repository. + +If you'd like to request that a new action, functional or control, be added, please [open an issue](https://github.com/arctic-hen7/perseus/issues/new/choose). + +- `tinker` -- see [this section](:reference/plugins/tinker) +- `settings_actions` -- actions that can alter the settings provided by the user with [`define_app!`](:reference/define-app) + - `add_static_aliases` -- adds extra static aliases to the user's app (e.g. a [TailwindCSS](https://tailwindcss.com) stylesheet) + - `add_templates` -- adds extra templates to the user's app (e.g. a prebuilt documentation system) + - `add_error_pages` -- adds extra [error pages](:reference/error-pages) to the user's app (e.g. a prebuilt 404 page) +- `build_actions` -- actions that'll be run when the user runs `perseus build` or `perseus serve` as part of the build process (these will not be run in [static exporting](:reference/exporting)) + - `before_build` -- runs arbitrary code just before the build process starts (e.g. to run a CSS preprocessor) + - `after_successful_build` -- runs arbitrary code after the build process has completed, if it was successful (e.g. copying custom files into `.perseus/dist/`) + - `after_failed_build` -- runs arbitrary code after the build process has completed, if it failed (e.g. to report the failed build to a server crash management system) + - `after_failed_global_state_creation` -- runs arbitrary code after if the build process failed to generate global state +- `export_actions` -- actions that'll be run when the user runs `perseus export` + - `before_export` -- runs arbitrary code just before the export process starts (e.g. to run a CSS preprocessor) + - `after_successful_build` -- runs arbitrary code after the build process has completed (inside the export process), if it was successful (e.g. copying custom files into `.perseus/dist/`) + - `after_failed_build` -- runs arbitrary code after the build process has completed (inside the export process), if it failed (e.g. to report the failed export to a server crash management system) + - `after_failed_export` -- runs arbitrary code after the export process has completed, if it failed (e.g. to report the failed export to a server crash management system) + - `after_failed_static_copy` -- runs arbitrary code if the export process fails to copy the `static` directory (e.g. to report the failed export to a server crash management system) + - `after_failed_static_alias_dir_copy` -- runs arbitrary code if the export process fails to copy a static alias that was a directory (e.g. to report the failed export to a server crash management system) + - `after_failed_static_alias_file_copy` -- runs arbitrary code if the export process fails to copy a static alias that was a file (e.g. to report the failed export to a server crash management system) + - `after_successful_export` -- runs arbitrary code after the export process has completed, if it was successful (e.g. copying custom files into `.perseus/dist/`) + - `after_failed_global_state_creation` -- runs arbitrary code if the export process failed to generate global state +- `export_error_page_actions` --- actions that'll be run when exporting an error page - `before_export_error_page` --- runs arbitrary code before this process has started (providing the error code to be exported for and the output file) + - `after_successful_export_error_page` -- runs arbitrary code after this process has completed, if it was successful + - `after_failed_write` -- runs arbitrary code after this process has completed, if it couldn't write to the target output file +- `server_actions` -- actions that'll be run as part of the Perseus server when the user runs `perseus serve` (or when a [serverful production deployment](:reference/deploying/serverful) runs) + - `before_serve` -- runs arbitrary code before the server starts (e.g. to spawn an API server) +- `client_actions` -- actions that'll run in the browser when the user's app is accessed + - `start` -- runs arbitrary code when the Wasm delivered to the browser is executed (e.g. to ping an analytics service) diff --git a/docs/next/en-US/plugins/intro.md b/docs/next/en-US/reference/plugins/intro.md similarity index 68% rename from docs/next/en-US/plugins/intro.md rename to docs/next/en-US/reference/plugins/intro.md index 7ef20512b2..637be83b34 100644 --- a/docs/next/en-US/plugins/intro.md +++ b/docs/next/en-US/reference/plugins/intro.md @@ -1,9 +1,9 @@ # Plugins -Perseus is extremely versatile, but there are some cases where is needs to be modified a little under the hood to do something very advanced. For example, as you'll learn [here](:deploying/size), the common need for applying size optimizations requires modifying a file in the `.perseus/` directory, which requires [ejecting](:ejecting). This is a laborious process, and makes updating difficult, so Perseus support a system of _plugins_ to automatically apply common modifications under the hood! +Perseus is extremely versatile, but there are some cases where is needs to be modified a little under the hood to do something very advanced. For example, as you'll learn [here](:reference/deploying/size), the common need for applying size optimizations requires modifying a file in the `.perseus/` directory, which requires [ejecting](:reference/ejecting). This is a laborious process, and makes updating difficult, so Perseus support a system of _plugins_ to automatically apply common modifications under the hood! First, a little bit of background. The `.perseus/` directory contains what's called the Perseus engine, which is basically the core of your app. The code you write is actually imported by this and used to invoke various methods from the `perseus` crate. If you had to build all this yourself, it would take a very long time! Because this directory can be automatically generated though, there's no need to check it into version control (like Git). However, this becomes problematic if you then want to change even a single file inside, because you'll then need to commit the whole directory, which can be unwieldy. More importantly, when updates come along that involve changes to that directory, you'll either have to delete it and re-apply your modifications to the updated directory, or apply the updates manually, either of which is overly tedious for simple cases. Perseus has plugins to help with this. At various points in the engine, plugins have what are called _actions_ that they can take. Those actions are then executed by the engine at the appropriate time. For example, if a plugin needed to run some code before a Perseus app initialized, it could do that by taking a particular action, and then the engine would execute that action just before the app initialized. -There are two types of actions a plugin can take: _functional actions_, and _control actions_. A single functional action can be taken by many plugins, and they (usually) won't interfere with each other. For example, many plugins can add additional [static aliases](:static-content) to an app. A single control action can only be taken by one plugin, because otherwise Perseus would have conflicting data. For example, if multiple plugins all set their own custom [immutable stores](:stores), Perseus wouldn't know which one to use. Both types of actions are explained in detail in the following sections. +There are two types of actions a plugin can take: _functional actions_, and _control actions_. A single functional action can be taken by many plugins, and they (usually) won't interfere with each other. For example, many plugins can add additional [static aliases](:reference/static-content) to an app. A single control action can only be taken by one plugin, because otherwise Perseus would have conflicting data. For example, if multiple plugins all set their own custom [immutable stores](:reference/stores), Perseus wouldn't know which one to use. Both types of actions are explained in detail in the following sections. diff --git a/docs/next/en-US/plugins/publishing.md b/docs/next/en-US/reference/plugins/publishing.md similarity index 100% rename from docs/next/en-US/plugins/publishing.md rename to docs/next/en-US/reference/plugins/publishing.md diff --git a/docs/next/en-US/plugins/security.md b/docs/next/en-US/reference/plugins/security.md similarity index 90% rename from docs/next/en-US/plugins/security.md rename to docs/next/en-US/reference/plugins/security.md index 70b6d4979a..67a518c979 100644 --- a/docs/next/en-US/plugins/security.md +++ b/docs/next/en-US/reference/plugins/security.md @@ -4,7 +4,7 @@ Perseus' plugins system makes it phenomenally versatile, and allows you to resha ## The Risks -If you enable a plugin in your app, it will have the opportunity to run arbitrary code. The actions that plugins take are just functions that they provide, so a plugin could easily be saying that it's adding an extra [static alias](:static-content) while simultaneously installing malware on your computer. +If you enable a plugin in your app, it will have the opportunity to run arbitrary code. The actions that plugins take are just functions that they provide, so a plugin could easily be saying that it's adding an extra [static alias](:reference/static-content) while simultaneously installing malware on your computer. ## Precautions diff --git a/docs/next/en-US/plugins/tinker.md b/docs/next/en-US/reference/plugins/tinker.md similarity index 62% rename from docs/next/en-US/plugins/tinker.md rename to docs/next/en-US/reference/plugins/tinker.md index b3664475a2..7d308dc89c 100644 --- a/docs/next/en-US/plugins/tinker.md +++ b/docs/next/en-US/reference/plugins/tinker.md @@ -1,6 +1,6 @@ # The `tinker` Action -There's one [functional action](:plugins/functional) that's quite special in Perseus: the `tinker` action. This action doesn't run as part of any of the usual processes, and it actually has its own command in the CLI: `perseus tinker`. That's because this action allows plugins to modify the code of the Perseus engine. For example, applying [size optimizations](:deploying/size) is a common requirement in Perseus apps, which means modifying `.perseus/Cargo.toml`. This is the perfect job for a plugin, but if it were done by any other action, you'd be modifying the `Cargo.toml` *after* the code had been compiled, which means the modifications would have no effect until the next run. +There's one [functional action](:reference/plugins/functional) that's quite special in Perseus: the `tinker` action. This action doesn't run as part of any of the usual processes, and it actually has its own command in the CLI: `perseus tinker`. That's because this action allows plugins to modify the code of the Perseus engine. For example, applying [size optimizations](:reference/deploying/size) is a common requirement in Perseus apps, which means modifying `.perseus/Cargo.toml`. This is the perfect job for a plugin, but if it were done by any other action, you'd be modifying the `Cargo.toml` _after_ the code had been compiled, which means the modifications would have no effect until the next run. The `tinker` action solves this problem by creating its own process that's specifically designed for engine modification and tweaking. Until [#59](https://github.com/arctic-hen7/perseus/issues/59) is resolved, this is how you'd make major modifications to the `.perseus/` engine efficiently. diff --git a/docs/next/en-US/plugins/using.md b/docs/next/en-US/reference/plugins/using.md similarity index 100% rename from docs/next/en-US/plugins/using.md rename to docs/next/en-US/reference/plugins/using.md diff --git a/docs/next/en-US/plugins/writing.md b/docs/next/en-US/reference/plugins/writing.md similarity index 70% rename from docs/next/en-US/plugins/writing.md rename to docs/next/en-US/reference/plugins/writing.md index 93fa73264b..0763253438 100644 --- a/docs/next/en-US/plugins/writing.md +++ b/docs/next/en-US/reference/plugins/writing.md @@ -4,18 +4,18 @@ Writing Perseus plugins is a relatively seamless process once you get the hang o ## Structure -A plugin will usually occupy its own crate, but it may also be part of a larger app that just uses plugins for convenience and to avoid [ejection](:ejecting). The only thing you'll need in a plugin is the `perseus` crate, though you'll probably want to bring other libraries in (like `sycamore` if you're adding templates or error pages). +A plugin will usually occupy its own crate, but it may also be part of a larger app that just uses plugins for convenience and to avoid [ejection](:reference/ejecting). The only thing you'll need in a plugin is the `perseus` crate, though you'll probably want to bring other libraries in (like `sycamore` if you're adding templates or error pages). ## Defining a Plugin To define a plugin, you'll call `perseus::plugins::Plugin::new()`, which takes four parameters: - The name of the plugin as a `&str`, which should be the name of the crate the plugin is in (or the name of a larger app with some extension) (**all plugins MUST have unique names**) -- A [functional actions](:plugins/functional) registrar function, which is given some functional actions and then extends them -- A [control actions](:plugins/control) registrar, which is given some control actions and then extends them +- A [functional actions](:reference/plugins/functional) registrar function, which is given some functional actions and then extends them +- A [control actions](:reference/plugins/control) registrar, which is given some control actions and then extends them - The environment for the plugin to run in (see below) -Here's an example of a very simple plugin that adds a static alias for the project's `Cargo.toml`, creates an about page, and prints the working directory at [tinker](:plugins/tinker)-time (taken from [here](https://github.com/arctic-hen7/perseus/blob/main/examples/plugins/src/plugin.rs)): +Here's an example of a very simple plugin that adds a static alias for the project's `Cargo.toml`, creates an about page, and prints the working directory at [tinker](:reference/plugins/tinker)-time (taken from [here](https://github.com/arctic-hen7/perseus/blob/main/examples/plugins/src/plugin.rs)): ```rust {{#include ../../../../examples/plugins/src/plugin.rs}} @@ -37,12 +37,12 @@ However, because Perseus is juggling all the data for all the plugins the user h Right now, there are few things that you can't do with Perseus plugins, which can be quite weird. -- You can't extend the engine's server (due to a limitation of Actix Web types), you'll need to manually run a `tinker` on it (add your code into the file by writing it in using [the `tinker` action](:plugins/tinker)) -- You can't set the [mutable store](:stores) from a plugin due to a traits issue, so you'll need to provide something for the user to provide to the `mutable_store` parameter of the `define_app!` macro +- You can't extend the engine's server (due to a limitation of Actix Web types), you'll need to manually run a `tinker` on it (add your code into the file by writing it in using [the `tinker` action](:reference/plugins/tinker)) +- You can't set the [mutable store](:reference/stores) from a plugin due to a traits issue, so you'll need to provide something for the user to provide to the `mutable_store` parameter of the `define_app!` macro - Similarly, you can't set the translations manager from a plugin ## Plugin Environments -As explained [here](:plugins/using), plugins can either run on the client (`PluginEnv::Client`), the server-side (`PluginEnv::Server`), or on both (`PluginEnv::Both`). Note that the server-side includes `tinker`-time and during the build process. If your plugin does not absolutely need to run on the client, use `PluginEnv::Server`! Your users will thank you for their much smaller bundles! If you don't do this, every single dependency of your plugin will end up in the user's final Wasm bundle, which has to be sent to browsers, and bundle sizes can end up doubling or more as a result! If this is the case though, make sure to tell your users to register your plugin using `.plugin_with_client_privilege()` rather than just `.plugin()` (but don't stress, they'll get an explanatory error if they use the wrong one accidentally). +As explained [here](:reference/plugins/using), plugins can either run on the client (`PluginEnv::Client`), the server-side (`PluginEnv::Server`), or on both (`PluginEnv::Both`). Note that the server-side includes `tinker`-time and during the build process. If your plugin does not absolutely need to run on the client, use `PluginEnv::Server`! Your users will thank you for their much smaller bundles! If you don't do this, every single dependency of your plugin will end up in the user's final Wasm bundle, which has to be sent to browsers, and bundle sizes can end up doubling or more as a result! If this is the case though, make sure to tell your users to register your plugin using `.plugin_with_client_privilege()` rather than just `.plugin()` (but don't stress, they'll get an explanatory error if they use the wrong one accidentally). You can set the environment your plugin runs on by changing the fourth argument to a variant of `PluginEnv`. diff --git a/docs/next/en-US/server-communication.md b/docs/next/en-US/reference/server-communication.md similarity index 78% rename from docs/next/en-US/server-communication.md rename to docs/next/en-US/reference/server-communication.md index 2932083a21..9e69aff2ca 100644 --- a/docs/next/en-US/server-communication.md +++ b/docs/next/en-US/reference/server-communication.md @@ -5,7 +5,7 @@ So far, we've described how to use Perseus to build powerful and performant fron
Frontend? Backend? -In web development, we typically refer to a project as having a *frontend*, which is the thing users see (i.e. your web app, with all its styling and the like), and a *backend*, which is a server or serverless function (see below) that performs server-side work. A classic example would be a server that communicates with a database to fetch some data, but it needs to authenticate against the database. If you're new to web dev, you might well be thinking we could just query the database from the web app, but that would mean we'd have to store the access token in our frontend code, which can be easily inspected by the user (albeit less easily with Wasm, but still definitely doable). For that reason, we communicate with a server and ask it to get the data from the database for us. +In web development, we typically refer to a project as having a _frontend_, which is the thing users see (i.e. your web app, with all its styling and the like), and a _backend_, which is a server or serverless function (see below) that performs server-side work. A classic example would be a server that communicates with a database to fetch some data, but it needs to authenticate against the database. If you're new to web dev, you might well be thinking we could just query the database from the web app, but that would mean we'd have to store the access token in our frontend code, which can be easily inspected by the user (albeit less easily with Wasm, but still definitely doable). For that reason, we communicate with a server and ask it to get the data from the database for us. Of course, a much simpler way of doing the above would be to make the database not need authentication in the first place, but the point stands. @@ -21,13 +21,13 @@ Instead, it's recommended that you create a server separate from Perseus that yo ### Serverless Functions -In the last few years, a new technology has sprung up that allows you to run individual *functions* (which might be single API routes) whenever they're requested. Infinitely many functions can be spawned simultaneously, and none will be active if none are being requested, which significantly reduces costs and increases scalability. This is provided by services like [AWS Lambda](https://aws.amazon.com/lambda/), and can be used with Rust via [this library](https://docs.rs/netlify_lambda_http). +In the last few years, a new technology has sprung up that allows you to run individual _functions_ (which might be single API routes) whenever they're requested. Infinitely many functions can be spawned simultaneously, and none will be active if none are being requested, which significantly reduces costs and increases scalability. This is provided by services like [AWS Lambda](https://aws.amazon.com/lambda/), and can be used with Rust via [this library](https://docs.rs/netlify_lambda_http). ## Querying a Server ### At Build-Time -It's fairly trivial to communicate with a server at build-time in Perseus, which allows you to fetch data when you build your app, and then your users don't have to do as much work. You can also use other strategies to fetch data [at request-time](:strategies/request-state) if needed. Right now, it's best to use a blocking API to make requests on the server, which you can do with libraries like [`ureq`](https://docs.rs/ureq). +It's fairly trivial to communicate with a server at build-time in Perseus, which allows you to fetch data when you build your app, and then your users don't have to do as much work. You can also use other strategies to fetch data [at request-time](:reference/strategies/request-state) if needed. Right now, it's best to use a blocking API to make requests on the server, which you can do with libraries like [`ureq`](https://docs.rs/ureq). One of the problems with fetching data at build time (or request-time, etc.) in development is that it often adds a significant delay to building your project, which slows you down. To solve this, Perseus provides two functions `cache_res` and `cache_fallible_res` that can be used to wrap your request code. They'll run it the first time, and then they'll cache the result to `.perseus/cache/`, which will be used in all future requests. These functions take a name (for the cache file), the function to run (which must be async), and a boolean that can be set to `true` if you want to temporarily disable caching. Usefully, these functions don't have to be removed for production, because they'll automatically avoid caching there. You can find an example of using these in [this example](https://github.com/arctic-hen7/perseus/tree/main/examples/fetching). @@ -35,10 +35,10 @@ Incidentally, you can also use those functions to work in an offline environment ### In the Browser -In some cases, it's just not possible to fetch the data you need on the server, and the client needs to fetch it themselves. This is often the case in [exported](:exporting) apps. This is typically done with the browser's inbuilt Fetch API, which is conveniently wrapped by [`reqwasm`](https://docs.rs/reqwasm). Note that you'll need to do this in a `Future`, which you can spawn using [`wasm_bindgen_futures::spawn_local`](https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.spawn_local.html), conveniently re-exported from Perseus as `perseus::spawn_local`. You can then modify a `Signal` in there that holds the data you want. It's common practice in web development today to show a page skeleton (those pulsating bars instead of text) while data are still being loaded. +In some cases, it's just not possible to fetch the data you need on the server, and the client needs to fetch it themselves. This is often the case in [exported](:reference/exporting) apps. This is typically done with the browser's inbuilt Fetch API, which is conveniently wrapped by [`reqwasm`](https://docs.rs/reqwasm). Note that you'll need to do this in a `Future`, which you can spawn using [`wasm_bindgen_futures::spawn_local`](https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.spawn_local.html), conveniently re-exported from Perseus as `perseus::spawn_local`. You can then modify a `Signal` in there that holds the data you want. It's common practice in web development today to show a page skeleton (those pulsating bars instead of text) while data are still being loaded. -However, if you try to request from a public API in this way, you may run into problems with [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), which can be very confusing, especially if you're not used to web development! The simple explanation of this is that CORS is a *thing* that browsers use to make sure your code can't send requests to servers that haven't allowed it (as in your code specifically). If you're querying your own server and getting this problem, make sure to set the `Access-Control-Allow-Origin` header to allow your site to make requests (see [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for more details). However, if a public API hasn't set this, you're up the creek! In these cases, it's best to query through your own server or through one of Perseus' rendering strategies (if possible). +However, if you try to request from a public API in this way, you may run into problems with [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), which can be very confusing, especially if you're not used to web development! The simple explanation of this is that CORS is a _thing_ that browsers use to make sure your code can't send requests to servers that haven't allowed it (as in your code specifically). If you're querying your own server and getting this problem, make sure to set the `Access-Control-Allow-Origin` header to allow your site to make requests (see [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for more details). However, if a public API hasn't set this, you're up the creek! In these cases, it's best to query through your own server or through one of Perseus' rendering strategies (if possible). ## Example -This can be confusing stuff, especially because it's different on the client and the server, so you may want to take a look at [this example](https://github.com/arctic-hen7/perseus/tree/main/examples/fetching) in the Perseus repo, which gets the IP address of the machine that built it, and then shows the user a message hosted with a [static alias](:static-content). +This can be confusing stuff, especially because it's different on the client and the server, so you may want to take a look at [this example](https://github.com/arctic-hen7/perseus/tree/main/examples/fetching) in the Perseus repo, which gets the IP address of the machine that built it, and then shows the user a message hosted with a [static alias](:reference/static-content). diff --git a/docs/next/en-US/snooping.md b/docs/next/en-US/reference/snooping.md similarity index 100% rename from docs/next/en-US/snooping.md rename to docs/next/en-US/reference/snooping.md diff --git a/docs/next/en-US/static-content.md b/docs/next/en-US/reference/static-content.md similarity index 100% rename from docs/next/en-US/static-content.md rename to docs/next/en-US/reference/static-content.md diff --git a/docs/next/en-US/stores.md b/docs/next/en-US/reference/stores.md similarity index 100% rename from docs/next/en-US/stores.md rename to docs/next/en-US/reference/stores.md diff --git a/docs/next/en-US/strategies/amalgamation.md b/docs/next/en-US/reference/strategies/amalgamation.md similarity index 68% rename from docs/next/en-US/strategies/amalgamation.md rename to docs/next/en-US/reference/strategies/amalgamation.md index dd2b7c061d..ea486ba622 100644 --- a/docs/next/en-US/strategies/amalgamation.md +++ b/docs/next/en-US/reference/strategies/amalgamation.md @@ -6,8 +6,8 @@ In the introduction to this section, we mentioned that all these rendering strat Here's an example from [here](https://github.com/arctic-hen7/perseus/blob/main/examples/showcase/src/templates/amalgamation.rs): -```rust,no_run,no-playground +```rust {{#include ../../../../examples/showcase/src/templates/amalgamation.rs}} ``` -This example illustrates a very simple amalgamation, taking the states of both strategies to produce a new state that combines the two. Note that this also uses `RenderFnWithCause` as a return type (see the section on the [_build state_](:strategies/build-state) strategy for more information). It will be passed an instance of `States`, which you can learn more about in the [API docs](https://docs.rs/perseus). As usual, serialization of your returned state is done with the `#[perseus::autoserde(amalgamate_states)]` macro, though the components of `States` will **not** be deserialized, and you'll have to do that manually. +This example illustrates a very simple amalgamation, taking the states of both strategies to produce a new state that combines the two. Note that this also uses `RenderFnWithCause` as a return type (see the section on the [_build state_](:reference/strategies/build-state) strategy for more information). It will be passed an instance of `States`, which you can learn more about in the [API docs](https://docs.rs/perseus). As usual, serialization of your returned state is done with the `#[perseus::autoserde(amalgamate_states)]` macro, though the components of `States` will **not** be deserialized, and you'll have to do that manually. diff --git a/docs/next/en-US/strategies/build-paths.md b/docs/next/en-US/reference/strategies/build-paths.md similarity index 100% rename from docs/next/en-US/strategies/build-paths.md rename to docs/next/en-US/reference/strategies/build-paths.md diff --git a/docs/next/en-US/strategies/build-state.md b/docs/next/en-US/reference/strategies/build-state.md similarity index 97% rename from docs/next/en-US/strategies/build-state.md rename to docs/next/en-US/reference/strategies/build-state.md index b887ab4ce0..05afa8e784 100644 --- a/docs/next/en-US/strategies/build-state.md +++ b/docs/next/en-US/reference/strategies/build-state.md @@ -4,7 +4,7 @@ The most commonly-used rendering strategy for Perseus is static generation, whic Note that, depending on other strategies used, Perseus may call this strategy at build-time or while the server is running, so you shouldn't depend on anything only present in a build environment (particularly if you're using the _incremental generation_ or _revalidation_ strategies). -_Note: if you want to export your app to purely static files, see [this section](:exporting), which will help you use Perseus without any server._ +_Note: if you want to export your app to purely static files, see [this section](:reference/exporting), which will help you use Perseus without any server._ ## Usage diff --git a/docs/next/en-US/strategies/incremental.md b/docs/next/en-US/reference/strategies/incremental.md similarity index 94% rename from docs/next/en-US/strategies/incremental.md rename to docs/next/en-US/reference/strategies/incremental.md index 8cabe5e434..821b438b5e 100644 --- a/docs/next/en-US/strategies/incremental.md +++ b/docs/next/en-US/reference/strategies/incremental.md @@ -1,6 +1,6 @@ # Incremental Generation -Arguable the most powerful strategy in Perseus is _incremental generation_, which is an extension of _build paths_ such that any path in the template's root path domain (more info on that concept [here](:templates/intro)) will result in calling the _build state_ strategy while the server is running. +Arguable the most powerful strategy in Perseus is _incremental generation_, which is an extension of _build paths_ such that any path in the template's root path domain (more info on that concept [here](:reference/templates/intro)) will result in calling the _build state_ strategy while the server is running. A perfect example of this would be an retail site with thousands of products, all using the `product` template. If we built all these with _build paths_, and they all require fetching information from a database, builds could take a very long time. Instead, it's far more efficient to use _incremental generation_, which will allow any path under `/product` to call the _build state_ strategy, which you can then use to render the product when it's first requested. This is on-demand building. But how is this different from the _request state_ strategy? It caches the pages after they've been built the first time, meaning **you build once on-demand, and then it's static generation from there**. In other words, this strategy provides support for rendering thousands, millions, or even billions of pages from a single template while maintaining static generation times of less than a second! diff --git a/docs/next/en-US/strategies/intro.md b/docs/next/en-US/reference/strategies/intro.md similarity index 100% rename from docs/next/en-US/strategies/intro.md rename to docs/next/en-US/reference/strategies/intro.md diff --git a/docs/next/en-US/strategies/request-state.md b/docs/next/en-US/reference/strategies/request-state.md similarity index 90% rename from docs/next/en-US/strategies/request-state.md rename to docs/next/en-US/reference/strategies/request-state.md index 3eef08344a..6a610bfa19 100644 --- a/docs/next/en-US/strategies/request-state.md +++ b/docs/next/en-US/reference/strategies/request-state.md @@ -8,11 +8,11 @@ If you can avoid this strategy, do, because it will bring your app's TTFB (time Here's an example taken from [here](https://github.com/arctic-hen7/perseus/blob/main/examples/showcase/src/templates/ip.rs) of using this strategy to tell the user their own IP address (albeit not hugely reliably as this header can be trivially spoofed, but this is for demonstration purposes): -```rust,no-run,no_playground +```rust {{#include ../../../../examples/showcase/src/templates/ip.rs}} ``` -Note that, just like _build state_, this strategy generates stringified properties that will be passed to the page to render it (serialization is handled by `#[perseus::autoserde(request_state)]`), and it also uses `RenderFnWithCause` (see the section on [build state](:strategies/build-state) for more information). The key difference though is that this strategy receives a second, very powerful parameter: the HTTP request that the user sent (`perseus::Request`). +Note that, just like _build state_, this strategy generates stringified properties that will be passed to the page to render it (serialization is handled by `#[perseus::autoserde(request_state)]`), and it also uses `RenderFnWithCause` (see the section on [build state](:reference/strategies/build-state) for more information). The key difference though is that this strategy receives a second, very powerful parameter: the HTTP request that the user sent (`perseus::Request`).
How do you get the user's request information? diff --git a/docs/next/en-US/strategies/revalidation.md b/docs/next/en-US/reference/strategies/revalidation.md similarity index 100% rename from docs/next/en-US/strategies/revalidation.md rename to docs/next/en-US/reference/strategies/revalidation.md diff --git a/docs/next/en-US/styling.md b/docs/next/en-US/reference/styling.md similarity index 97% rename from docs/next/en-US/styling.md rename to docs/next/en-US/reference/styling.md index 5f441deda5..c8b6b5dc41 100644 --- a/docs/next/en-US/styling.md +++ b/docs/next/en-US/reference/styling.md @@ -2,7 +2,7 @@ Perseus aims to make styling as easy as possible, though there are a number of things that you should definitely know about before you start to style a Perseus app! -It's very easy to import stylesheets with Perseus (be they your own, something like [TailwindCSS](https://tailwindcss.com), etc.). You just add them to the `static/` directory at the root of your project, and then they'll be available at `/.perseus/static/your-filename-here`. That's described in more detail in [this section](:static-content). +It's very easy to import stylesheets with Perseus (be they your own, something like [TailwindCSS](https://tailwindcss.com), etc.). You just add them to the `static/` directory at the root of your project, and then they'll be available at `/.perseus/static/your-filename-here`. That's described in more detail in [this section](:reference/static-content). ## Full-Page Layouts @@ -13,7 +13,9 @@ Notably, there are actually two of these `
`s at the moment: one for the con Knowing this, the main changes you'll need to make to any full-page layout code is to apply the styles to `.__perseus_content` as well as `body` or `#root`. As with CSS generally, if you expect `.__perseus_content` to take up the whole page, you'll need to make all its parents (`#root`, `body`, `html`) also take up the whole page (you can do this by setting `height: 100vh;` on `body`). A good starting point (that supports scrolling as well) is this CSS: ```css -body, #root, .__perseus_content { +body, +#root, +.__perseus_content { min-height: 100%; min-width: 100%; height: 100vh; diff --git a/docs/next/en-US/templates/intro.md b/docs/next/en-US/reference/templates/intro.md similarity index 100% rename from docs/next/en-US/templates/intro.md rename to docs/next/en-US/reference/templates/intro.md diff --git a/docs/next/en-US/templates/metadata-modification.md b/docs/next/en-US/reference/templates/metadata-modification.md similarity index 100% rename from docs/next/en-US/templates/metadata-modification.md rename to docs/next/en-US/reference/templates/metadata-modification.md diff --git a/docs/next/en-US/templates/router-state.md b/docs/next/en-US/reference/templates/router-state.md similarity index 100% rename from docs/next/en-US/templates/router-state.md rename to docs/next/en-US/reference/templates/router-state.md diff --git a/docs/next/en-US/templates/setting-headers.md b/docs/next/en-US/reference/templates/setting-headers.md similarity index 100% rename from docs/next/en-US/templates/setting-headers.md rename to docs/next/en-US/reference/templates/setting-headers.md diff --git a/docs/next/en-US/testing/checkpoints.md b/docs/next/en-US/reference/testing/checkpoints.md similarity index 100% rename from docs/next/en-US/testing/checkpoints.md rename to docs/next/en-US/reference/testing/checkpoints.md diff --git a/docs/next/en-US/testing/fantoccini-basics.md b/docs/next/en-US/reference/testing/fantoccini-basics.md similarity index 93% rename from docs/next/en-US/testing/fantoccini-basics.md rename to docs/next/en-US/reference/testing/fantoccini-basics.md index 85c36286f1..3fe61f5239 100644 --- a/docs/next/en-US/testing/fantoccini-basics.md +++ b/docs/next/en-US/reference/testing/fantoccini-basics.md @@ -10,7 +10,7 @@ Remember, you're controlling an actual browser, so you basically have everything ## Going to a Page -You can trivially go to a page of your app by running `c.goto("...")`. The above example ensures that the URL is valid, but you shouldn't have to do this unless you're testing a page that automatically redirects the user. Also, if you're using [i18n](:i18n/intro), don't worry about testing automatic locale redirection, we've already done that for you! +You can trivially go to a page of your app by running `c.goto("...")`. The above example ensures that the URL is valid, but you shouldn't have to do this unless you're testing a page that automatically redirects the user. Also, if you're using [i18n](:reference/i18n/intro), don't worry about testing automatic locale redirection, we've already done that for you! Once you've arrived at a page, you should wait for the `router_entry` (this example uses `begin` because it tests internal parts of Perseus) checkpoint, which will be reached when Perseus has decided what to do with your app. If you're testing particular page logic, you should wait instead for `page_visible`, which will be reached when the user could see content on your page, and then for `page_interactive`, which will be reached when the page is completely ready. Remember though, you only need to wait for the checkpoints that you actually use (e.g. you don't need to wait for `page_visible` and `page_interactive` if you're not doing anything in between). diff --git a/docs/next/en-US/testing/intro.md b/docs/next/en-US/reference/testing/intro.md similarity index 100% rename from docs/next/en-US/testing/intro.md rename to docs/next/en-US/reference/testing/intro.md diff --git a/docs/next/en-US/testing/manual.md b/docs/next/en-US/reference/testing/manual.md similarity index 100% rename from docs/next/en-US/testing/manual.md rename to docs/next/en-US/reference/testing/manual.md diff --git a/docs/next/en-US/updating.md b/docs/next/en-US/reference/updating.md similarity index 95% rename from docs/next/en-US/updating.md rename to docs/next/en-US/reference/updating.md index 4f9499ccc7..1541162615 100644 --- a/docs/next/en-US/updating.md +++ b/docs/next/en-US/reference/updating.md @@ -5,10 +5,10 @@ Perseus v0.3.0 added significant architectural changes to Perseus under the hood 1. Update your `Cargo.toml` dependencies for `perseus` to `0.3`. 2. Upgrade the Perseus CLI with `cargo install perseus-cli`. 3. Run `perseus clean` to remove the old `.perseus/` directory. -4. Remove any custom config managers you may have, they've been replaced by [mutable and immutable stores](:stores). +4. Remove any custom config managers you may have, they've been replaced by [mutable and immutable stores](:reference/stores). 5. Take anything Perseus-related wrapped in `Rc::new` (these will be all through your template definitions and error pages) and remove the `Rc::new`, Perseus now handles that internally, with no performance cost! 6. If you're using i18n, add the `translator-fluent` flag to `perseus` in your `Cargo.toml`. If you're not, your Wasm bundle size has been reduced! -7. Change any uses of the `HOST` and `PORT` environment variables to the `--host` and `--port` flags on `perseus serve` in development, and use `PERSEUS_HOST` and `PERSEUS_PORT` in production. The original environment variable names will still work in deployments, but they'll be deprecated in v0.4.0. +7. Change any uses of the `HOST` and `PORT` environment variables to the `--host` and `--port` flags on `perseus serve` in development, and use `PERSEUS_HOST` and `PERSEUS_PORT` in production. The original environment variable names will still work in deployments, but they'll be deprecated in v0.4.0. 8. Update your code for the remaining breaking changes listed in [the CHANGELOG](https://github.com/arctic-hen7/perseus/blob/main/CHANGELOG). Perseus v0.3.0 also changed a few common idioms, like breaking out the `.template()` call into a separate function `template_fn()`. This is no longer recommended, though it will still work fine. You can check out the [examples directory](https://github.com/arctic-hen7/perseus/tree/main/examples) to see how things are a bit nicer now in terms of formatting. diff --git a/docs/next/en-US/views.md b/docs/next/en-US/reference/views.md similarity index 100% rename from docs/next/en-US/views.md rename to docs/next/en-US/reference/views.md diff --git a/docs/next/en-US/hello-world.md b/docs/next/en-US/tutorials/hello-world.md similarity index 100% rename from docs/next/en-US/hello-world.md rename to docs/next/en-US/tutorials/hello-world.md diff --git a/docs/next/en-US/second-app.md b/docs/next/en-US/tutorials/second-app.md similarity index 100% rename from docs/next/en-US/second-app.md rename to docs/next/en-US/tutorials/second-app.md