Writers camps
Org-run songwriting camps that group studio sessions, manage a roster of writers, collect a signature on the camp's own terms, and let people join either by personal invite (auto-join) or a public open-form signup link (with an optional price to join that can be invoiced per participant from the camp's People page, a signup wave with limited spots + waitlist, and a full public camp page. Schedule, hosts, FAQ, travel, partners). Logged-in applicants can review, edit, or opt out of their submission. Camps surface on the in-app calendar, ICS feeds, the MCP server, and mobile, and unfurl with a rich OG image when shared.
What it is
A writers camp is a songwriting event an organisation runs: a roster of writers and producers, a set of studio sessions over a few days, and the tracks that come out of it. The organiser builds the lineup, schedules people into sessions, and afterwards reviews the songs and decides what to do with each one.
People get into a camp in one of two ways:
- Personal invite: the organiser adds someone by name/email and Aden sends them a private invite link. Opening it (and signing in or creating an account) joins them to the camp automatically, no extra "accept" step.
- Open signup link: the organiser turns on a public signup page and shares one link. Anyone with it can view the camp and apply without signing in (no account required to apply); the organiser then accepts or rejects each application. If you're already signed in to Aden the form shows your account and lets you pick which of your teams you're attending with.
Partner organisations. A camp can be co-run by more than one organisation. The hosting organisation invites another organisation from the camp's Organisations page; once that organisation's admins accept, the camp shows up in their own camps list and sidebar with a live view of the sessions, the studios they're rented in, the people, and the tracks produced. Managing the camp (settings, roster changes, invites) stays with the host, and either side can end the link at any time.
Using it
Run a camp (organiser).
- Create a camp under your organisation and set its dates, location, and
branding (logo + banner). The new-camp form has a Plan the sessions
helper: enter how many writers join and pick a group size to get a suggested
group count, then set Sessions at once (parallel rooms), Minutes per
session, and a Daily hours window and hit Generate: it lays out
one pre-titled slot per group across the camp's start date, pairing parallel
groups into the same time block and stepping blocks through the daily window,
rolling onto the next day when the window fills. Generated slots (and any
added by hand) can each be removed, including the last one. The form owns a
single
useFieldArrayfor the slots and passes it down to the sharedCampSessionSlotsField, so generation and manual edits stay in sync. The form also collects the full Where block (location label, venue name, street address, city, country. EverythingcreateCampaccepts), and each session slot has a collapsible Location section (label/venue/city/ country, auto-expanded when values exist) via the sharedCampLocationFieldscomposable; slot payloads go through onesessionSlotToPayloadmapper. The whole draft: camp fields plus planned sessions: autosaves to localStorage (useLocalFormDraft, keyed per org+kind), restores on revisit, and clears after a successful create; the Sessions dialog's one-off tab drafts the same way (keyed per camp). The new-camp page is a full-width three-rail workspace: a stickyScrollStepperrail on the left (Details / Location / Plan / Sessions, driven by an IntersectionObserver scroll-spy like the release-plan workspace), the form in the middle, and a live read-only calendarCampSchedulePreviewon the right that groups valid slots into per-day columns over a shared time axis and packs concurrent sessions side by side, updating as slots are generated/edited (below thelgbreakpoint the rails collapse and the preview renders inline). Time controls honour the app-wide 12h/24h time-format preference (useEffectiveTimeFormat): the Daily hours pickers use the sharedInputTime, which now formats via that preference, as does the preview; the per-slot start/end pickers still use the native time input (OS-locale display). - On the People page, add writers from your organisation/teams or invite new
people by name and email. While the camp is a draft, invites are queued. Hit
Send invites (which also publishes a draft camp) to email everyone at
once. The page is split into
server-side
?tab=lineup|roster|add|applications|responsestabs (each tab's data streams in under its own Suspense boundary so the send-invite actions never wait on the slow lineup query). The tab strip renders in the shared underline-tab style with an icon per tab and no full-width divider. The Roster tab lists everyone on the camp and lets organisers remove a participant from the camp entirely (removeCampParticipant: also drops them from any sessions). Across Roster, Applications and Responses, each person renders with their avatar (resolved fromavatar_keyin one batched call) via the sharedCampPersonIdentity: on-platform people link to their public passport page (/user/[userId]), the team they signed up with shows as aCampTeamBadge(team avatar, links to/profile/[slug]), and a quick-message button (CampPersonMessageButton) opens the org chat with a new conversation preselected for them (/org/[orgId]/chat?createWithMember=<userId>, handled by the chat workspace like?createWithTrack=) or falls back tomailto:for email-only participants. The Add people tab embeds the sameCampAddPeoplePanel(shared collaborator invite panel) as the Sessions page's Add people dialog. One component (_components/camp-add-people.tsx) for both surfaces. The new-camp form's people pool runs the same panel with the artist-team tab enabled: the camp has no id yet, so a team joins as the rows picked from it and each row carries itsteamIduntilcreateCampreturns and the drafts flush throughinviteCampPeople. - Optionally open the camp's public signup link in Settings → Public signup, add an intro, and share the link anywhere.
- Build the lineup by dragging people into sessions, or hit Do it with AI
on the People page: pick an AI model (all free-on-plan, served via NVIDIA
NIM like the in-app chat), optionally add instructions ("keep Anna
and Bob together"), and it proposes who goes into which session with roles
and a reason per pairing. Nothing is saved until you review the proposal,
remove anything you disagree with, and apply it. Then send everyone their
personal schedule. Drops are optimistic: the person shows up in the session
column immediately (pending spinner) and rolls back with an error toast if
the schedule action fails; removing someone from a session hides them
immediately the same way. Each session card on the lineup links out to the
full session editor on the team sessions surface
(
/app/teams/[teamId]/sessions/[sessionId]) for rich editing, and the quick-edit dialog can link a real studio room from the organisation's studios (studio_id) instead of only free-text venue fields. - On the Sessions page, one New sessions dialog covers both planning
modes: Plan a week creates sessions in bulk (one title per line × every
day in a date range, all at the same start/end times, live count preview
capped at 61 days) via
createCampSessions; One-off sessions keeps the repeatable custom slots. Import sessions takes the schedule the camp was planned in: an Excel file (.xlsx), a CSV, or rows pasted straight out of a sheet. Clean columns (title, start, end, location, header optional) map on their own; a messy sheet goes through Map with AI. Either way the parsed sessions are listed for review before anything is created. Add people opens the shared collaborator invite panel (same one as session participants): pick people from the org's writers/members/team members, invite someone new by email, or pick an artist team and choose who comes with them. Picking a team loads its people throughgetInvitableTeamMembersActionand pre-fills its artists as rows, so a camp can take an artist plus their two writers instead of the whole roster; each picked row is invited throughinviteCampParticipantwithteamIdset, so the roster shows their team badge. Clearing every row falls back toinviteCampTeam, which fans the team's activeuser_teamsmembers intocamp_participantsrows (dupes by user/email skipped, no emails sent until the camp publishes,team_idstamped on each row). The camp mixes freely: foreign artists with their own teams, unaffiliated songwriters invited by email, and org writers all land in the same pool. Pool and member avatars resolve fromavatar_keyvia the batched optimized-URL helpers. - The camp overview calendar also supports click-and-drag to create a
session on a specific day and time (week/day views), plus a right-click /
hover-
+create menu on day cells. The same interaction as the personal/app/calendar. Dragging a time range opens a quick "New session" dialog pre-filled with the picked start/end; confirming creates the session viacreateCampSessions. This rides the sharedEventCalendar'screateItemTypesprop (passed['session']) so the drag-create picker only ever offers a session. The org breadcrumb resolves the camp id to the camp's name (via the layout'sx-pathname+ request-dedupedgetCampDetail).
Join by personal invite. Open the link from your email. If you already have an Aden account you sign in; if not, you create one (no invite code needed). As soon as you're signed in you're dropped straight into the camp. If the invite includes a document to sign, you sign it first, then join.
Join by open signup link. Open the link (no login needed) and fill in your name, what you play, an optional note, and any custom questions the organisers added. The camp's location links straight out to maps. If you're signed in, your account is shown and you can choose which team you're attending with; otherwise you can still apply as yourself. Your application goes to the organisers, who accept or reject it. You'll hear back by email.
Price to join. Organisers can optionally set a price to join a camp (shown on the public signup page as a "… to join" badge, with an optional note after it like "+ VAT"). Leave it empty to keep the camp free.
Invoice the people who join. People → Invoices lists everyone holding a spot next to their invoice state (not invoiced / draft / unpaid / overdue / paid). Tick the people you want to bill and hit Create invoices: the amount per person is prefilled with the camp's join price, and you set the VAT rate and due date once for the batch. Leave Issue and email now off to get drafts you can still edit, or switch it on to number them and email each participant the amount and payment reference straight away. Everything lands in the organisation's normal invoice list, so PDFs, e-invoice exports, reminders and mark-as-paid all work the same as any other invoice. An issued invoice also gets its own public page. The participant's email links straight to it, and the roster row has an open-invoice button, so people without an Aden account can read the invoice and its payment reference. Nobody can be billed twice someone with a live invoice can't be selected again until it's canceled.
One contract everyone signs. Under Settings → Contract organisers write the camp's terms (splits, confidentiality, code of conduct, travel. Markdown) and/or upload a contract PDF, and choose whether it must be signed before joining. The title is optional. Left blank it is taken from the uploaded file's name, or falls back to "<camp> contract". Organisers can also attach extra documents (house rules, travel brief, studio map): they ride along with the contract and are readable/downloadable on the signing page, but are never signed. From then on everyone who lands on the roster is asked to sign it: invited people get it with their invite (and, when it's required, sign it on the invite page before they're let into the camp), accepted applicants and open-signup joiners get it the moment they're in. Signing runs through the normal Aden flow. A private link, a saved signature, a signed PDF with a certificate, and a verification page, so it behaves like every other contract. People → Roster shows a Signed / To sign badge per person; opening it gives the contract title, the signing date, a link to the signed copy (or the signing page), a copy-the-link action for chasing, and the public verification page. Send to everyone on the roster catches up anyone added before the contract existed (nobody is asked twice).
The public camp page. The signup link is the camp's own page, not just a form. Under Settings → Public page organisers fill in as much or as little as they want, and each block only appears once it has content:
- Schedule: day by day ("Monday", "Tue – Thu"), each with timed items (welcome reception, breakfast, writing sessions, listening session, transfers). Free-text times, so "evening" works as well as "9:00".
- What's included: what the join price covers, plus a price note.
- Getting there: routes, transfers, nearest airport and station.
- The team: hosts with a photo, role and short bio.
- Your rights: where masters and publishing land, and any first-option arrangement.
- FAQ: grouped by category (Funding / General / Technical), rendered as one accordion per group.
- Testimonials, partners (label, sponsors), and a contact block with email, phone and social links.
Signup waves, spots and the waitlist. Camps run in rounds. Under Settings → Public signup organisers set a wave name ("Wave 2"), when signups open and close, and how many spots there are:
- Outside the window, or once the camp is full, the form is replaced by a "notify me" box: nobody hits a dead end. Organisers can write their own closed message ("we're reviewing round 1, wave 2 opens 1 August").
- With waitlist on, a full camp keeps taking applications; they arrive as waitlisted and never auto-join. Accepting one from the People page promotes it into the camp.
- When 10 or fewer spots remain, the page shows a real "3 spots left" badge.
- People who already applied keep seeing their own submission after the wave closes (locked, not editable).
A custom public link. By default the public page lives on the unguessable
token (/camps/898o8-rx0RJ…). Under Settings → Public signup organisers can
claim a readable alias instead, /camps/durbuy-camp-2026, validated as
lowercase letters, numbers and dashes and unique across all camps. The token
link keeps resolving to the same page, so anything already shared stays valid.
The camp name in the header doubles as a menu (open the public page, copy the
link, jump to applications), and the applications tab carries the same copy/open
link above the queue.
Interest list. Everyone who left their email while signups were shut lands on People → Interest, where organisers can copy every address or open a pre-filled draft to tell them the next wave is open.
Benefits (what you get). Organisers can list the perks participants get a sponsor goodie bag, hardware, plugin licenses. Under Settings → Benefits. They show on the public signup page as a "What you get" list, and on People → Roster each participant gets a gift button with a delivered counter so the team can tick off what has actually been handed out (goodie-bag logistics).
Edit or opt out after signing up. If you're signed in and have already applied or joined, the signup page shows your existing submission with its status instead of a blank form. You can edit your name, roles, note, and answers, or opt out to remove your submission (you can sign up again later if you change your mind).
See your camps everywhere. Camps you're part of show up on your Aden calendar as a multi-day event, in any calendar you've subscribed to via the camp's ICS feed, and in the Aden mobile app under a dedicated Camps screen.
End-of-camp listening session. After a camp, the Listening tab plays every final track and records what happens with each one. Release, pitch, hold, or archive, with optional notes. Two things you can do with that session:
- Share it. Create a public link (with a QR code) that anyone can open without an account to hear the final tracks and see your decisions. Toggle the link off and on at any time; turning it off makes the link stop working without losing it.
- Convert it to a playlist. Turn every final camp track into a playlist in one click, then keep editing, reordering, or sharing it like any other playlist.
Track requests
Publish a brief (e.g. a remix contest) and collect structured submissions, uploaded audio files or links, into your demo inbox, with a public remixes page on the track, optional social-follow gating and shareable stems.
Writers camps
Organise songwriting camps, a people pool, session lineup, public signup forms with custom questions, and end-of-camp track decisions, inside an organisation.