f6ae86617c
Co-authored-by: Copilot <copilot@github.com>
207 lines
7.9 KiB
Markdown
207 lines
7.9 KiB
Markdown
# Getting Started
|
|
|
|
This guide walks you through everything you need to get the project running locally — from installing tools to understanding why certain architectural decisions were made.
|
|
|
|
---
|
|
|
|
## What is in this solution
|
|
|
|
| Project | Purpose |
|
|
|---|---|
|
|
| `Htmx.ApiDemo` | ASP.NET Core web app using Minimal APIs and server-rendered HTMX templates |
|
|
| `Htmx.SourceGenerator` | Roslyn source generator that reads `.htmx` template files and generates endpoint mapping code at build time |
|
|
|
|
The solution file is `Htmx.slnx` at the repository root.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
Install the following before cloning the repo.
|
|
|
|
### .NET SDK
|
|
|
|
The project targets `net10.0`. Download the .NET 10 SDK from [dot.net](https://dotnet.microsoft.com/download).
|
|
|
|
Verify with:
|
|
|
|
```bash
|
|
dotnet --version
|
|
```
|
|
|
|
### Node.js and npm
|
|
|
|
Tailwind CSS is compiled during the build using the Tailwind CLI via `npx`. Node.js must be installed.
|
|
|
|
Download from [nodejs.org](https://nodejs.org). Verify with:
|
|
|
|
```bash
|
|
node -v
|
|
npm -v
|
|
```
|
|
|
|
### MongoDB
|
|
|
|
The app stores data in MongoDB. You need a local instance running on `mongodb://localhost:27017`.
|
|
|
|
**Windows:**
|
|
|
|
Download and install [MongoDB Community Server](https://www.mongodb.com/try/download/community). During installation, choose to run MongoDB as a Windows Service so it starts automatically.
|
|
|
|
**Linux:**
|
|
|
|
Follow the official guide for your distro at [docs.mongodb.com/manual/administration/install-on-linux](https://www.mongodb.com/docs/manual/administration/install-on-linux/). For Ubuntu/Debian:
|
|
|
|
```bash
|
|
sudo systemctl start mongod
|
|
sudo systemctl enable mongod # start on boot
|
|
```
|
|
|
|
**MongoDB Compass (optional but recommended):**
|
|
|
|
Compass is a GUI for browsing and querying your MongoDB data. Download it from [mongodb.com/products/compass](https://www.mongodb.com/products/compass). Connect it to `mongodb://localhost:27017` to inspect collections while developing.
|
|
|
|
---
|
|
|
|
## VS Code setup
|
|
|
|
### Required extensions
|
|
|
|
- **C# Dev Kit** — provides IntelliSense, debugging, and project support for .NET
|
|
Search for `ms-dotnettools.csdevkit` in the Extensions panel.
|
|
|
|
- **C# (OmniSharp / Roslyn)** — included with C# Dev Kit but can also be installed standalone as `ms-dotnettools.csharp`.
|
|
|
|
### Recommended settings
|
|
|
|
Add the following to your workspace or user `settings.json`. This teaches VS Code to treat `.htmx` files as HTML (for syntax highlighting and formatting) and nests generated companion files under their parent in the Explorer sidebar so the file tree stays clean.
|
|
|
|
```jsonc
|
|
{
|
|
"files.associations": {
|
|
"*.htmx": "html"
|
|
},
|
|
"explorer.fileNesting.enabled": true,
|
|
"explorer.fileNesting.expand": false,
|
|
"explorer.fileNesting.patterns": {
|
|
"*.razor": "$(capture).razor.cs, $(capture).razor.css, $(capture).razor.js",
|
|
"*.htmx": "${capture}.htmx.cs, ${capture}.htmx.routing.cs, ${capture}.g.cs, ${capture}.css"
|
|
}
|
|
}
|
|
```
|
|
|
|
Without `files.associations`, `.htmx` files open as plain text with no highlighting. Without file nesting, every generated `.htmx.cs` and `.htmx.routing.cs` file appears as a separate top-level entry in the Explorer, making it hard to navigate.
|
|
|
|
### Optional extension
|
|
|
|
- **Tailwind CSS Fold** — collapses long Tailwind class strings in the editor so markup is easier to read. Search for `stivo.tailwind-fold`. This is purely a cosmetic convenience and has no effect on the build.
|
|
|
|
---
|
|
|
|
## Understanding AOT
|
|
|
|
AOT (Ahead-of-Time compilation) means the app is compiled to native machine code before it runs, rather than relying on the .NET JIT at runtime. This project has AOT enabled (`<PublishAot>true</PublishAot>` in the `.csproj`).
|
|
|
|
### Why AOT matters here
|
|
|
|
AOT produces smaller, faster deployments with no JIT warmup time. For a web app handling many requests, startup time and binary size are real concerns — especially in containerized or serverless environments.
|
|
|
|
### What AOT prevents you from doing
|
|
|
|
AOT is a significant constraint. It eliminates entire categories of patterns that are common in standard .NET development:
|
|
|
|
- **No Entity Framework Core** — EF Core relies heavily on runtime reflection and expression compilation. It is not AOT-compatible. This project uses the MongoDB driver directly instead.
|
|
|
|
- **No runtime reflection** — `Type.GetProperties()`, `Activator.CreateInstance()`, dynamic proxies, and similar patterns do not work (or produce warnings/errors) under AOT. If a pattern depends on inspecting types at runtime, it will not survive.
|
|
|
|
- **Many NuGet packages are incompatible** — Any package that uses reflection internally (serializers, mappers, validators, ORMs, DI containers with convention scanning, etc.) may break. Check a package's AOT compatibility before adding it.
|
|
|
|
- **Source generator-based serialization required** — Rather than `JsonSerializer.Serialize(myObject)` discovering properties at runtime, you must register types with a `JsonSerializerContext` subclass (see `AppJsonSerializerContext.cs`). The serializer then uses generated code instead of reflection.
|
|
|
|
- **Route handler code generation** — ASP.NET Core's Minimal API generator produces code for request binding and response writing. Some third-party packages produce code that conflicts with this. If adding a package causes build errors in generated files, AOT incompatibility is the likely cause.
|
|
|
|
The practical rule: before reaching for a package or pattern you know from standard ASP.NET Core, check whether it is AOT-compatible. The project will compile normally in Debug mode even with AOT-incompatible code — AOT issues typically only surface during `dotnet publish`.
|
|
|
|
---
|
|
|
|
## First-time setup
|
|
|
|
Clone the repo, then install the npm dependencies that the build needs:
|
|
|
|
```bash
|
|
cd Htmx.ApiDemo
|
|
npm install
|
|
```
|
|
|
|
This installs the Tailwind CSS CLI package. The build runs `npx @tailwindcss/cli` as an MSBuild step, so if this is skipped the build will fail with a missing command error.
|
|
|
|
---
|
|
|
|
## Run the app
|
|
|
|
From the repository root:
|
|
|
|
```bash
|
|
dotnet run --project Htmx.ApiDemo/Htmx.ApiDemo.csproj
|
|
```
|
|
|
|
The app listens on `http://localhost:5120` by default (configured in `Htmx.ApiDemo/Properties/launchSettings.json`).
|
|
|
|
---
|
|
|
|
## Verify it works
|
|
|
|
1. Open `http://localhost:5120` in your browser.
|
|
2. If you are not signed in, the middleware redirects you to `/login` — this is expected.
|
|
3. Go to `/register` and create an account.
|
|
4. Sign in and explore the app.
|
|
|
|
---
|
|
|
|
## What happens at startup
|
|
|
|
`Program.cs` wires up the following in order:
|
|
|
|
- MongoDB service registration and index initialization (`EnsureIndexesAsync`)
|
|
- Cookie-based authentication and authorization
|
|
- Antiforgery middleware
|
|
- AOT-compatible JSON serialization via `AppJsonSerializerContext`
|
|
- All generated HTMX endpoints via `app.MapHtmxApiDemoEndpoints()`
|
|
|
|
---
|
|
|
|
## Build details
|
|
|
|
- **Tailwind** is compiled into `wwwroot/css/output.css` as a pre-build step.
|
|
- **`.htmx` files** are passed to the source generator as `<AdditionalFiles>`. The generator reads them and produces the abstract base classes and routing code.
|
|
- **AOT** is active on publish. Run a publish build early and often to catch incompatibilities before they accumulate.
|
|
|
|
### Publish (AOT)
|
|
|
|
```bash
|
|
dotnet publish Htmx.ApiDemo/Htmx.ApiDemo.csproj -c Release
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Build fails — Tailwind command not found
|
|
|
|
Run `npm install` inside the `Htmx.ApiDemo` directory. Confirm `node` and `npm` are on your `PATH`.
|
|
|
|
### MongoDB connection errors at startup
|
|
|
|
- Confirm the MongoDB service is running (`mongod`).
|
|
- Check that `ConnectionStrings:DefaultConnection` in `appsettings.json` points to `mongodb://localhost:27017`.
|
|
|
|
### App always redirects to `/login`
|
|
|
|
This is intentional. Unauthenticated requests are redirected by the auth middleware. Register at `/register` first.
|
|
|
|
### AOT warnings or errors on publish
|
|
|
|
- Look at the warning message — it usually names the type or method causing the issue.
|
|
- Remove or replace the offending package or pattern with an AOT-compatible alternative.
|
|
- Run `dotnet publish` regularly during development so issues do not pile up.
|