Skip to content


The current document describes the stages of recruitment and the various evaluation points that occur during the process.

Launch of a recruitment round

  • The epic planning managers are responsible for determining when the availability needs of their cells will require launching a recruitment round. They communicate this need as much as possible in advance to the recruitment manager and the CEO - ideally at least 1 month before the availability is required, to provide enough time to complete the round.
    • A cell should always target having some extra availability, to allow to accept new projects without requiring too much last-minute recruitment, which is more stressful for the cell and the recruitment manager. On top of the required availability, plan for 1-2+ extra newcomers for availability margin, plus planning ahead to replace any newcomer that doesn't pass their trial.
  • The CEO publishes the job ad, which direct candidates to submit the recruitment form.
  • The CEO informs the team's recruitment manager of the upcoming start of a recruitment round, and creates a workflow board to track the progression of the round's process.
  • The recruitment manager includes a ticket in their upcoming sprint for it, and mentions in the comments of the workflow board how many newcomers they are looking for.
  • The candidatures are available to the recruitment manager immediately upon submission, without filtering. The recruitment manager assigns the unassigned candidatures to themselves, starting with the oldest submissions.
  • This self-assignment operation can be repeated up to every two days by the recruitment manager (which might be necessary if recruitment needs are high and/or candidatures are being reviewed quickly).

Pre-selection of candidates for interviews

The recruitment manager does a pre-selection of candidatures to invite for an interview. It is a very basic filter over the candidatures - we don't want to be too selective at this stage, as it can still be quite hard to tell whether a candidate would be a good fit just from that information. So there are few criteria, but they are strict - if a candidate fails to pass any of these, they are eliminated:

Contribution to third party projects

We want to see at least one contribution (PR/patch) to a third party project, which isn't completely trivial (a small bug fix is fine, but just fixing a typo, spacing or a missing import isn't enough, you want to be able to have something to evaluate), and which has been merged by the third party project.

No exceptions on this, it's a hard rule. This is the main filter of the pre-selection. So we check this first, and generally someone saying explicitly that they don't have contributions is enough to rule them out -- in these cases we save time by not having to look at the rest of the candidature.


  • The type of work/tech from the contributions don't need to be related to our work.
  • The recipient project can be small, but should be something that has users (see its number of stars & forks - there should be at least 10-20 of each).
  • PRs done as part of an employment are ok (that's also what we do!), but it should really be done openly, and still preferably to a third party. If the PRs are all silently merged, it means there was either no review, or it happened privately, and this doesn't really qualify as an open source contribution
  • There should also be at least a PR description, and some comments/discussions with upstream - we are looking for people who communicate.
  • We are trying to filter for people who care about contributing to someone else's project, so merely releasing code on their github, or even contributions to a project they are a maintainer of, doesn't count.
  • Since often candidates just point at their github account, we get all their third-party PRs by visiting this URL (we check this for both the github & gitlab accounts when they are provided):
    • Github:
    • Gitlab:

Proper writing skills

Candidates don't need to have flawless spelling & grammar, but it needs to be reasonable. We think about whether the type of writting would work with a client for example. We aren't too harsh though - it can be hard to tell at times, and we can give the benefit of the doubt.

Python, Django & React

We require experience in at least Python & Django, plus preferably React. Sometimes it's unclear - some candidates don't specify some of their experience... So we wouldn't necessarily eliminate a promising candidate who doesn't list one of those (and React is not mandatory either, just very appreciated), but we will take a note of any doubt on these, to ask during the interview.

Although if there is no mention or sign of any practice of Python, the candidate almost certainly has no Python experience, so we reject the candidature in these cases. Some candidates omit mentioning Django when they have only a small amount of experience with it, and it's still fine in that case after verification, but nobody fluent in a language omits mentioning it in their list of skills, especially when other languages are mentioned.


We also currently don't hire junior developers - from past experiences, the remote environment combined to the expected quality and efficiency doesn't work well with junior profiles, at least with our current organization. We might revisit this in the future, but we would need to put in place a specific process to allow them to acquire the required skills and experience.

At the moment, we require at least 2-3 years of professional experience as a hired developer. We sometimes make an exception for a prolific open source contributor who has demonstrated great technical and social skills in his contributions, and thus already shows a senior profile.

Also, we accept candidates who have been recently been employed by another Open edX provider, but we check for exclusivity clauses in their contract before proceeding with an interview (to be discussed with the CEO when someone from another provider applies).

Fields to fill

In the spreadsheet containing the candidatures, besides the answers submitted by candidates, the recruitment manager will see a few additional columns to fill:

  • Status: The current status of the candidature (drop-down).

  • Python, Django, React: This is a reminder to write in the cell any of those skills for which the candidate isn't clearly experimented And then, during the interview, we ask the candidate about it. Sample value: "Django? React?" => which would be completed with the answer during the interview. For candidates which have all three pre-requirements, we put "OK" in this column - this helps ensuring that we remembered to check (or to ask).

  • Comments: Meant to contain the explanation for the recruitment manager's decision.

  • The other fields are for the interview itself - see below.

Scheduling interviews

Emailing selected candidates

The recruitment manager sends an email to each candidate that they selected. We use a standard email template for the content of that email. Make sure to CC the recruitment@ mailing-list in your exchanges with candidates, to allow others to follow.

Scheduling through Calendly

We use Calendly to schedule interviews. Get an account from Xavier if you don't already have one, and setup a dedicated event for interviews:

  • Open for the week following the pre-selection
  • At times which allow a reasonable coverage of most timezones (the afternoon UTC time is usually good for that)
  • Make sure to keep the times narrow, to allow to batch the interviews - it's best for focus to not end up having them spread all over your days
  • Enable Calendar invitations, to automatically send Google Calendar invites
  • Link it to the OpenCraft Zoom account (to allow to host longer meetings), and enable the automated inclusion of a Zoom URL in the meeting invite

We need to record interviews to allow for later review by other team members. To ensure we don't forget to start the recording during the meeting, we enable the option ahead of time, in the scheduled meeting details. The setting for each individual scheduled meeting should look like this:


Recording in the cloud offer the best/most reliable way to ensure the meeting will have been recorded.

To be able to keep the candidate's reactions visible in the recording, even when they are not talking, make sure to select "Record gallery view with shared screen" in your account settings:




The interviews lasts 30 minutes, and we use a script. The script is private, to not demesurably advantage candidates who read the handbook ahead of the interview.

We don't necessarily say exactly and only the content of the script (we are not a call center ;p), but we try to stick to it, as the more similar it is across interviews, the better we are able to compare them with each other. This is especially true of the code exercise, where the way to explain it can influence significantly what the candidate will understand and how they will approach it.


During the interview, we progressively grade the candidate in the corresponding columns of the spreasheet, with a short comment on each. The rating is 1 to 5, with 5 being the highest. E.g. "5 - aced the exercise!".

Video recording upload

We then upload the video recording of the interview to our private file drive, using the 'Gallery view' file. Also add a link in the candidate's spreadsheet entry, in the dedicated column. This will allow other team members to review it.

Final selection of newcomers

  • The recruitment manager takes a decision on whether to hire the candidate as a newcomer.
  • The Admin Specialist reviews the selection and interviews. If it looks like a candidate could be confirmed, the Admin Specialist meets with the candidate for a second interview, to take a decision and to discuss contracting terms. These additional steps can be viewed here.
  • The recruitment manager sends a rejection email to the candidates who have been refused.

Administrative specialist — Recruitment tasks details

This section details the Admin specialist's tasks for team member onboarding and offboarding, the steps of which are found on our team member recruitment onboarding and offboarding template.

The first set of tasks is when a new team member starts their trial.

The second set of tasks is when the newcomer becomes a core member of the OpenCraft team.

The third set of tasks is when someone leaves OpenCraft, as we must offboard that user from our tools.

Onboarding a new team member in the OpenCraft Billing app

You will need to have the team member's contract at hand. The contract can be found in the Contractors Drive folder, which is only shared with the Admin Specialist.

Log into the Billing app to execute the following tasks:

Create a new Django user

Create a Django user by going to AuthenticationUsersAdd.

  • Use their Jira username as the Django username
  • Add a random but secure password — no need to note it.
  • Click Save and continue editing
  • Add their Full Name and their email (usually
  • Save

Create and associate a Provider account

Create a Provider account to associate the Django user with a Provider account (the entity that will get paid). This is done by going to AccountAccountsAdd + User→ Choose the correct Django/Jira user + Add the user's Address (can be found on the contract) + Business name should be the same as on the contract + Occupation and VAT should be left blank by default + Save

Create an invoice template

Create an invoice template by going to InvoicesInvoice templatesAdd.

  • Choose the right Provider, which is the Account you just created.
  • Set Numbering scheme to {number} by default.
  • Don't touch the other fields. Newcomers will tell you if they need anything different once they see their first invoice.
  • Save

Add and activate an hourly rate

Add and activate their hourly rate by going to AccountsHourly ratesAdd.

  • Set Hourly rate. The value must be in Euros.
  • Choose the right Provider, which is the Account you just created.
  • Set Client to OpenCraft GmbH.
  • Check the Active box to activate the rate.
  • Important note on when to activate the rate: When the team members' invoice generation process starts (on the 3rd of the month), invoices will be generated for all users who have the Active box checked. If a newcomer is onboarded early in the month, and has not logged time in the previous month, do not activate their rate until after the team member invoices have been generated (after the 6th of the month). Take a note or schedule a task as a reminder. If the Active box is checked right away, the invoice-generating script will scrape the hours from the previous month and won't find any hours — it will therefore generate a €0 invoice. Our accountants hate €0 invoices, so please avoid them!
  • Save

Request bank information

Ask them for their bank and bank account information.

Always add in CC when discussing billing with team members.

The specific bank account information that we need depends on the country where the bank account is hosted. Here's how to find out what banking information is required:

  • Log into your Wise account, and click Recipients in the left sidebar, and then click the Add Recipient button in the upper central menu.
  • Choose Currency, then check Business, and take note of the fields that appear under Bank details — this is the info that you'll need to ask.
  • If you cannot choose Business, then it means Wise business transfers aren't supported for that currency, and that deposits will have to be made manually by Xavier using the Volksbank account instead. In those cases, warn Xavier by email and ask him to collect the necessary details with the newcomer so that he can set up the transfers manually.

Once you have noted the bank info fields from Wise, send an email to the newcomer, asking them to provide the info, along with:

  • Bank's BIC/Swift number
  • Account number or IBAN
  • Account type (checking or savings)
  • Currency to be used for deposits. We can do EUR, USD, or local currency. If newcomer wants deposits in EUR or USD, have them confirm that their bank account will accept the currency.
Simple email template to request banking information

I'm NAME and I handle administration at OpenCraft. Welcome to the team : )

I'm preparing your profile in our billing app, and I'll need your bank information. Can you please provide the following:
(list of info)

Thank you, and let me know if you have any questions!

Once you have obtained the information, add it to the Billing app by following these steps:

Adding a new bank
  • Go to BankBanksAdd
  • Name should be formated like this : #bank_name — #team_member_name, e.g. "Cool Bank Ltd. - Joe Banana"
  • Add the bank's Address. The address we're looking for here is the one associated with the bank's SWIFT/BIC number. To find the address, use an online tool such as this one, and use the address that is displayed there. This process has proven to give more reliable results than asking the newcomer for their bank's address.
  • Important note: The country of the bank account must match the Provider's country. If the bank is located in a country that is different from the Provider's address on their contract, a proof of ownership of the bank account must be provided, such as a statement or a letter from the bank.
  • Save
Adding a bank account
  • Go to BankBank AccountsAdd
  • Choose the Bank
  • Choose the Provider
  • Set account Type to checking or savings, depending on the info provide by the newcomer
  • The Transferwise recipient ID will be added by Xavier later in the process, no action required at this stage
  • The Identification field has to be filled out by editing the boilerplate text and adding the values between the quotes (BIC/SWIFT number, Account number, Currency)
  • Note: if the newcomer provided an IBAN, this is the Account number).
  • Save
  • Schedule a task for Xavier to generate a Wise recipient ID, which is used for automated payments. In the task description, link to the newcomer's bank account page in Billing so that Xavier has easy access to the information. If you're onboarding multiple team members within the same month, try to group all requests in the same task so that Xavier can do it in batch. Once done, Xavier will either add the ID himself in the bank account info, or he'll give you the ID and you can go and add it yourself.

Confirming a core team member

Add core team member's name and location to the map tool on our website

When a team member makes it into the core team, the CEO or Recruitment Manager will ping the Admin Specialist to add the new core team member on the website world map tool. Instructions for adding users on the map tool are found in our website theme README. This process requires using a vector drawing editor such as Inkscape, Adobe Illustrator or an online tool such as Method Draw. The team member's current location can be found in the HR contact spreadsheet.

Offboarding - When a user leaves OpenCraft

Change tream member's email in the Billing app to their personal email

This is done in the Django users config page at AuthenticationUsers#user . Their personal email can be found on the last page of their contract.

Remove user from world map

Remove the user's name by deleting their line from about.twig (or just their name, if they're in a city where we have multiple team members) and creating a pull request. Ask another team member to review before merging.

Deactivate their rate from the billing system.

Once their last payment has been sent, go to the user's hourly rate and uncheck the Active box.

Note: Do this after their last invoice is generated, and before the next invoicing cycle begins (to avoid generating a €0 invoice).