Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TripNotes

A personal trip-journal app: log trips and notes, and get instant, offline-capable full-text search across every entry — powered by a build-time Pagefind search index instead of a database LIKE query or a hosted search service.

Backend: ASP.NET Core 10 minimal API + EF Core 10 + PostgreSQL (Docker Compose). Frontend: React 19 + TypeScript 7 + Vite 8 + Tailwind CSS v4. Search: Pagefind, 100% client-side against a static index rebuilt from the data.

Prerequisites

Setup from a clean clone

1. Environment file

cp .env.example .env

The defaults work as-is for local development. .env is git-ignored — never commit it.

2. Start PostgreSQL

docker compose up -d

This starts Postgres 17 in a container with a named volume (tripnotes-db-data), empty. Schema comes only from EF Core migrations — there's no seed SQL and no manual DDL.

3. Apply migrations

cd backend/TripNotes.Api
dotnet ef database update

If dotnet ef isn't installed:

dotnet tool install --global dotnet-ef --version 10.0.12
export PATH="$PATH:$HOME/.dotnet/tools"   # add to your shell profile to persist

4. Run the backend API

cd backend/TripNotes.Api
dotnet run --urls http://localhost:5032

Verify it's up: curl http://localhost:5032/api/trips should return [] on a fresh database. In development mode, the OpenAPI document is at http://localhost:5032/openapi/v1.json. TripNotes.Api.http has a full request sequence you can run from VS Code's REST Client / Rider / IntelliJ HTTP client.

5. Run the frontend

In a separate terminal:

cd frontend
npm install
npm run dev

Open http://localhost:5173. The dev server proxies /api/* to the backend at localhost:5032, and the backend's CORS policy also allows that origin directly.

Create a trip, add a couple of notes — this is real data going into your local Postgres, no mock/demo data anywhere.

6. Build the search index

The backend has no search endpoint — search is 100% client-side against a static index built from your data:

cd frontend
npm run build-search-index

This fetches /api/export from the running backend, writes one HTML fragment per note, runs Pagefind over them, and writes the index to frontend/public/pagefind/ (git-ignored, regenerated on demand). The dev server serves it immediately — reload the page and search should return your real notes.

Re-run this manually any time your data changes — it is not automatic. If you add, edit, or delete a trip/note and want it reflected in search, re-run the command above.

7. Run the backend tests

cd backend
dotnet test

These are integration tests that boot the real API via WebApplicationFactory and hit it over HTTP — not mocks. They run against a separate tripnotes_test database on the same Postgres container (auto-created and migrated on first run), so docker compose up -d must be running first. Tables are truncated between tests; your tripnotes (dev) database is never touched.

"Nuke and rebuild" the database

To reset to a completely clean database (e.g. after pulling a new migration, or if data gets into a weird state):

docker compose down -v && docker compose up -d
cd backend/TripNotes.Api && dotnet ef database update

down -v removes the named volume, so the next up starts Postgres from scratch, and database update reapplies every migration in order from nothing.

Project layout

tripnotes/
├── backend/
│   ├── TripNotes.Api/              # ASP.NET Core minimal API
│   │   ├── Models/                 # Trip, NoteEntry (EF Core entities)
│   │   ├── Data/                   # DbContext, migrations, design-time factory
│   │   ├── Dtos/                   # request/response records
│   │   ├── Endpoints/              # route group extension methods
│   │   └── TripNotes.Api.http      # exercise every route manually
│   ├── TripNotes.Api.Tests/        # MSTest integration tests
│   └── TripNotes.slnx
├── frontend/
│   ├── src/
│   │   ├── api/                    # typed fetch client for the backend
│   │   ├── components/             # TripList, TripForm, NoteEditor
│   │   ├── hooks/                  # useTrips, useNotes
│   │   └── search/                 # SearchBox + pagefind.js loader
│   ├── scripts/build-search-index.mjs
│   └── public/pagefind/            # generated, git-ignored
├── docker-compose.yml              # Postgres only
├── .env.example
└── CLAUDE.md                       # project instructions for AI-assisted development

API surface

Route Description
GET /api/trips List trips
POST /api/trips Create a trip
GET /api/trips/{id} Get a trip
PUT /api/trips/{id} Update a trip
DELETE /api/trips/{id} Delete a trip (cascades its notes)
GET /api/trips/{id}/notes List notes for a trip
POST /api/trips/{id}/notes Create a note under a trip
PUT /api/notes/{id} Update a note
DELETE /api/notes/{id} Delete a note
GET /api/export Full trips+notes JSON dump — the only thing the search indexer consumes

There is no /api/search — search is entirely client-side.

Non-goals

No authentication, no cloud deployment/CI, no mobile app, no photo upload, no real-time sync, no tags/categories. See CLAUDE.md for the full rationale — this is a scoped weekend build, not a product.

Definition of done checklist

  • docker compose up -d starts Postgres cleanly; dotnet ef database update applies migrations to a fresh volume with no manual steps.
  • dotnet run starts the API; all CRUD routes work via the .http file.
  • npm run dev starts the frontend; trips and notes can be created/edited/deleted against the real API.
  • node scripts/build-search-index.mjs produces a working index; typing in the search box returns real matches from actually-typed note content.
  • dotnet test passes.
  • This README documents the full setup from a clean clone.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages