diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..788b2db --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,21 @@ +name: ๐Ÿงผ Formatting + +on: push + +jobs: + markdown-lint: + runs-on: ubuntu-latest + steps: + - name: Checkout your repository using git + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install dependencies + run: npm install + + - name: Run Markdown Lint + run: npm run format:check diff --git a/cspell.json b/cspell.json index d501c92..a50728a 100644 --- a/cspell.json +++ b/cspell.json @@ -1,17 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", "version": "0.2", - "ignorePaths": [ - "node_modules/**", - ".**/" - ], - "files": [ - "**/*.md", - "**/*.mdx", - "**/*.tsx", - "**/*.ts", - "**/*.json" - ], + "ignorePaths": ["node_modules/**", ".**/"], + "files": ["**/*.md", "**/*.mdx", "**/*.tsx", "**/*.ts", "**/*.json"], "words": [ "ABAP", "Abuild", diff --git a/src/content/docs/architecture/backend.md b/src/content/docs/architecture/backend.mdx similarity index 90% rename from src/content/docs/architecture/backend.md rename to src/content/docs/architecture/backend.mdx index 3b82cb4..2240018 100644 --- a/src/content/docs/architecture/backend.md +++ b/src/content/docs/architecture/backend.mdx @@ -3,6 +3,8 @@ title: Backend Architecture description: Best practices for building backend APIs. --- +import { FileTree } from "@astrojs/starlight/components"; + Loose coupling, separation of concerns and layered architecture should not only be applied to frontend development. These principles can also be applied during backend development. For example, concepts such as route navigation, data access, data processing and data models can be separated and tested in isolation. :::note @@ -29,39 +31,40 @@ Putting the backend in the same repository as the frontend allows developers to While providers, routes, and tests, can live in the root backend project, consider putting data models and data access into their own dedicated package(s). Ideally, these layers should be able to exist independently from the rest of the app. -```txt -my_app/ - |- api/ - | |- lib/ - | | |- src/ - | | | |- middleware/ - | |- packages/ - | | |- models/ - | | | |- lib/ - | | | | |- src/ - | | | | | |- endpoint_models/ - | | | | | |- shared_models/ - | | | |- test/ - | | | | |- src/ - | | | | | |- endpoint_models/ - | | | | | |- shared_models/ - | | |- data_source/ - | | | |- lib/ - | | | | |- src/ - | | | |- test/ - | | | | |- src/ - | |- routes/ - | | |- api/ - | | | |- v1/ - | | | | |- todos/ - | | |- test/ - | | | |- src/ - | | | | |- middleware/ - | | | |- routes/ - | | | | |- api/ - | | | | | |- v1/ - | | | | | | |- todos/ -``` + + +- api/ + - lib/ + - src/ + - middleware/ + - packages/ + - models/ + - lib/ + - src/ + - endpoint_models/ + - shared_models/ + - test/ + - src/ + - endpoint_models/ + - shared_models/ + - data_source/ + - lib/ + - src/ + - test/ + - src/ + - routes/ + - api/ + - v1/ + - todos/ + - test/ + - src/ + - middleware/ + - routes/ + - api/ + - v1/ + - todos/ + + ### Models diff --git a/src/content/docs/architecture/barrel_files.md b/src/content/docs/architecture/barrel_files.mdx similarity index 74% rename from src/content/docs/architecture/barrel_files.md rename to src/content/docs/architecture/barrel_files.mdx index be6cae7..7cbf3d3 100644 --- a/src/content/docs/architecture/barrel_files.md +++ b/src/content/docs/architecture/barrel_files.mdx @@ -3,39 +3,45 @@ title: Barrel Files description: Best practices for exposing public facing files. --- +import { FileTree } from "@astrojs/starlight/components"; + When building a package, a feature, or an API, we will create a folder structure with all the source code inside. If we stop here and don't export the files that will be required in other places of the app, we will force developers to have a long and messy import section. Furthermore, any refactor that affects file names in one feature will require changes in other places that could be avoided. For a package, the structure could look something like: -```text -my_package/ - |-lib/ - | |- src/ - | | |- models/ - | | | - model_1.dart - | | | - model_2.dart - | | |- widgets/ - | | | - widget_1.dart - | | | - widget_2.dart - |- test/... - |- pubspec.yaml -``` + + +- my_package/ + - lib/ + - src/ + - models/ + - model_1.dart + - model_2.dart + - widgets/ + - widget_1.dart + - widget_2.dart + - test/... + - pubspec.yaml + + And for a feature, it could look like: -```text -my_feature/ - |- bloc/ - | - feature_bloc.dart - | - feature_event.dart - | - feature_state.dart - |- view/ - | - feature_page.dart - | - feature_view.dart - |- widgets/ - - widget_1.dart - - widget_2.dart -``` + + +- my_feature/ + - bloc/ + - feature_bloc.dart + - feature_event.dart + - feature_state.dart + - view/ + - feature_page.dart + - feature_view.dart + - widgets/ + - widget_1.dart + - widget_2.dart + + In both cases, if we want to use both `widget_1.dart` and `widget_2.dart` in other parts of the app, we will have to import them separately like: @@ -56,37 +62,41 @@ With these changes, let's update the folder structures for both scenarios. A package with barrel files should look like: -```text -my_package/ - |-lib/ - | |- src/ - | | |- models/ - | | | - model_1.dart - | | | - model_2.dart - | | | - models.dart - | | |- widgets/ - | | | - widget_1.dart - | | | - widget_2.dart - | | | - widgets.dart - | |- my_package.dart - |- test/... - |- pubspec.yaml -``` + + +- my_package/ + - lib/ + - src/ + - models/ + - model_1.dart + - model_2.dart + - models.dart + - widgets/ + - widget_1.dart + - widget_2.dart + - widgets.dart + - my_package.dart + - test/... + - pubspec.yaml + + And for a feature, it should look like: -```text -my_feature/ - |- bloc/ - | - feature_bloc.dart - | - feature_event.dart - | - feature_state.dart - |- view/ - | - feature_page.dart - | - feature_view.dart - | - view.dart - |- my_feature.dart -``` + + +- my_feature/ + - bloc/ + - feature_bloc.dart + - feature_event.dart + - feature_state.dart + - view/ + - feature_page.dart + - feature_view.dart + - view.dart + - my_feature.dart + + Finally let's see what these files contain. Continuing with the package example, we have three barrel files: `models.dart`, `widgets.dart` and `my_package.dart`. @@ -119,12 +129,14 @@ In this example, we are exporting all files from the folder, but this is not alw By convention, blocs are typically broken into separate files consisting of the events, states, and the bloc itself: -```text -bloc/ + + +- bloc/ - feature_bloc.dart - feature_event.dart - feature_state.dart -``` + + In this case, we don't add an extra barrel file since the `feature_bloc.dart` file is working as such, thanks to the `part of` directives. You can read more about it in the [bloc documentation][bloc_documentation]. diff --git a/src/content/docs/navigation/navigation.mdx b/src/content/docs/navigation/navigation.mdx index 94ac713..d1eec9f 100644 --- a/src/content/docs/navigation/navigation.mdx +++ b/src/content/docs/navigation/navigation.mdx @@ -19,26 +19,30 @@ Structure your routes in a way that makes logical sense. Avoid placing all of yo - ```txt - / - /flutter - /flutter/news - /flutter/chat - /android - /android/news - /android/chat - ``` + +```txt +/ +/flutter +/flutter/news +/flutter/chat +/android +/android/news +/android/chat +``` + - ```txt - / - /flutter - /flutter-news - /flutter-chat - /android - /android-news - /android-chat - ``` + +```txt +/ +/flutter +/flutter-news +/flutter-chat +/android +/android-news +/android-chat +``` + @@ -106,15 +110,20 @@ For reasons listed in the [Prefer navigating by name over path](#prefer-navigati + ```dart context.goNamed('categories', queryParameters: {'size': 'small', 'color': 'blue'}) ``` + + Navigating by path: + ```dart context.go('/categories?size=small&color=blue'); ``` + ::: @@ -151,15 +160,19 @@ Mobile app users will likely never see your route's path, but web app users can - ```txt - /user/update-address - ``` + +```txt +/user/update-address +``` + - ```txt - /user/update_address - /user/updateAddress - ``` + +```txt +/user/update_address +/user/updateAddress +``` + @@ -224,14 +237,18 @@ GoRouter provides extension methods on `BuildContext` to simplify navigation. Fo - ```dart - context.goNamed('flutterNews'); - ``` + +```dart +context.goNamed('flutterNews'); +``` + - ```dart - GoRouter.of(context).goNamed('flutterNews'); - ``` + +```dart +GoRouter.of(context).goNamed('flutterNews'); +``` + diff --git a/src/content/docs/testing/testing.md b/src/content/docs/testing/testing.mdx similarity index 93% rename from src/content/docs/testing/testing.md rename to src/content/docs/testing/testing.mdx index 2e79663..4f8e1af 100644 --- a/src/content/docs/testing/testing.md +++ b/src/content/docs/testing/testing.mdx @@ -5,6 +5,8 @@ sidebar: order: 1 --- +import { FileTree, TabItem, Tabs } from "@astrojs/starlight/components"; + At Very Good Ventures, our goal is to achieve 100% test coverage on all projects. Writing tests not only helps to reduce the number of bugs, but also encourages code to be written in a very clean, consistent, and maintainable way. While testing can initially add some additional time to the project, the trade-off is fewer bugs, higher confidence when shipping, and less time spent in QA cycles. ## Organize test files @@ -13,41 +15,51 @@ Test files should be organized to match your project file structure. This `my_package` library contains `models` and `widgets`. The `test` folder should copy this structure: -```txt -my_package/ - |- lib/ - | |- models/ - | | - model_a.dart - | | - model_b.dart - | | - models.dart - | |- widgets/ - | | - widget_1.dart - | | - widget_2.dart - | | - widgets.dart - |- test/ - ... -``` + -Bad โ—๏ธ +- my_package/ + - lib/ + - models/ + - model_a.dart + - model_b.dart + - models.dart + - widgets/ + - widget_1.dart + - widget_2.dart + - widgets.dart + - test/ + ... -```txt -test/ - |- model_a_test.dart - |- model_b_test.dart - |- widgets_test.dart -``` + -Good โœ… + + + -```txt -test/ - |- models/ - | - model_a_test.dart - | - model_b_test.dart - |- widgets/ - | - widget_1_test.dart - | - widget_2_test.dart -``` + - test/ + - models/ + - model_a_test.dart + - model_b_test.dart + - widgets/ + - widget_1_test.dart + - widget_2_test.dart + + + + + + + + + - test/ + - model_a_test.dart + - model_b_test.dart + - widgets_test.dart + + + + + > Note: `models.dart` and `widgets.dart` are barrel files and do not need to be tested.