{"id":50936034,"url":"https://github.com/ducks/discourse-itinerary","last_synced_at":"2026-06-17T09:02:07.428Z","repository":{"id":360125127,"uuid":"1248547503","full_name":"ducks/discourse-itinerary","owner":"ducks","description":"Turn a Discourse category into a travel itinerary. Topics become flights, hotels, trains, and events sorted by date.","archived":false,"fork":false,"pushed_at":"2026-06-11T19:07:19.000Z","size":197,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T21:06:05.315Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ducks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T19:34:59.000Z","updated_at":"2026-06-11T19:07:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ducks/discourse-itinerary","commit_stats":null,"previous_names":["ducks/discourse-itinerary"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ducks/discourse-itinerary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducks%2Fdiscourse-itinerary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducks%2Fdiscourse-itinerary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducks%2Fdiscourse-itinerary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducks%2Fdiscourse-itinerary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ducks","download_url":"https://codeload.github.com/ducks/discourse-itinerary/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducks%2Fdiscourse-itinerary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34441285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-17T09:02:06.473Z","updated_at":"2026-06-17T09:02:07.420Z","avatar_url":"https://github.com/ducks.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# discourse-itinerary\n\nA Discourse plugin that turns a category of topics into a chronological\ntravel itinerary, with one trip per topic and its items linked back to it.\n\nTopics in the configured itinerary category that carry a set of itinerary\ncustom fields are collected, grouped under their parent trip, sorted by\nstart time, and returned via plugin routes. Ember pages render the list\nof trips and the per-trip timeline grouped by day.\n\nThis is an early, narrow tool. It is not a generic notes app, calendar, or\nproject planner. It just makes a category of Discourse topics readable as a\ntravel timeline.\n\n## How it works\n\n- **Category** = container for many trips. The plugin auto-creates an\n  \"Itinerary\" category on first boot and stores its id in the\n  `itinerary_category_id` site setting; admins can repoint that setting\n  at a different category if they want.\n- **Topic with `itinerary_item_type = trip`** = the trip workspace\n- **Other itinerary topics** = items (flight, hotel, train, event, transfer,\n  note) that point at their parent trip via `itinerary_parent_trip_id`\n- **Topic custom fields** = structured metadata\n- **Plugin routes**: `GET /itinerary/trips` (list trips, optionally\n  filtered by `category_id`), `GET /itinerary/trips/:id` (one trip\n  with its items, day-grouped on the client)\n- **Pages**: `/itinerary` (trip list) and `/itinerary/:trip_id` (timeline)\n\n### Custom fields\n\nEach itinerary topic stores these fields on the standard topic\n`custom_fields` table:\n\n| Field                          | Type     | Example                 |\n| ------------------------------ | -------- | ----------------------- |\n| `itinerary_item_type`          | string   | `flight`                |\n| `itinerary_starts_at`          | string   | `2026-09-20T14:30`      |\n| `itinerary_ends_at`            | string   | `2026-09-21T09:15`      |\n| `itinerary_origin`             | string   | `PDX`                   |\n| `itinerary_destination`        | string   | `MAD`                   |\n| `itinerary_name`               | string   | `Memmo Alfama`          |\n| `itinerary_location`           | string   | `Artrip, Madrid`        |\n| `itinerary_confirmation_code`  | string   | `ABC123`                |\n| `itinerary_status`             | string   | `booked`                |\n\nTimestamps are stored as ISO-8601 strings; sorting is lexical.\n\n## Status\n\n- **v0.1** — JSON route + Rails-side query\n- **v0.2** — composer extension for authoring itinerary topics\n- **v0.3** - team-trip data model (one category, many trips), split\n  finders, trip + item JSON routes, Ember route and timeline rendering\n- **v0.4** - auto-create dedicated category; drop tag requirement\n- **v0.5** - hide itinerary category from /latest by default so the\n  plugin owns the UX; /itinerary is the canonical entrypoint, with\n  a sidebar link under the Community section and +Add buttons on\n  both the trip list and per-trip timeline pages\n- **v0.6** - auto-synthesize topic title and body from itinerary\n  fields. Hide the bare title input; pre-fill the body. Item topics\n  no longer require the user to invent a title.\n- **v0.7** - iCalendar (.ics) export per trip. Download a single\n  calendar file containing one VEVENT per item with a start time;\n  import into Apple Calendar, Google Calendar, or Outlook.\n- **later** — filters, status tracking, drag-reorder, per-user\n  subscribe URLs so calendar apps can subscribe rather than download\n\nNo calendar sync, email parsing, or map view. Not planned for the near term.\nICS export shipped in v0.7.\n\n## Site settings\n\n- `itinerary_enabled` (default: true) — kill switch for the plugin\n- `itinerary_category_id` (default: -1) - id of the category the plugin\n  treats as the itinerary workspace. Auto-set on first boot when the\n  plugin provisions its default category; can be repointed in admin.\n\n## Requirements\n\n- A Discourse category to hold itinerary topics. The plugin creates one\n  automatically on first boot if `itinerary_category_id` is unset.\n\n## Local development\n\nA `shell.nix` is shipped for the linter/test workflow:\n\n```sh\nnix-shell                              # ruby 3.3 + bundler + native deps\nbundle install                         # installs gems into ./.gems\nbundle exec rubocop                    # lint Ruby\nbundle exec stree check $(git ls-files '*.rb') Gemfile\n```\n\nTo run the specs you need a Discourse checkout — symlink the plugin in and\nrun rspec from there:\n\n```sh\nln -s $PWD ~/discourse/discourse/plugins/discourse-itinerary\ncd ~/discourse/discourse\nbin/rspec plugins/discourse-itinerary/spec/\n```\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fducks%2Fdiscourse-itinerary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fducks%2Fdiscourse-itinerary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fducks%2Fdiscourse-itinerary/lists"}