There are complex solutions and easy solutions. The two easiest solutions are:
Fan out recurring events up to some constant number of instances, or up to some fixed date range in the future. Store a FK recurrence_id with each instance that points to a description of the recurrence, and allows for mass editing and canceling.
The advantage of the pre-calced fan out approach is it makes it very very easy to implement recurrence exceptions, which will almost certainly be the first feature request you get.
Calculate at display time. Computers are fast, depending on the questions you want to be able to answer about your data, it will often be trivially easy to calculate all the occurrences in a date range. You can be smart and try to quickly bracket your date range before doing the recurrence calculation, or you can brute force it from the onset date.
Beyond that you just need a solution for storing the recurrence rule that works with whatever you're using to calculate recurrences. (e.g. if you're using an iCalendar enable library, your schema is varchar(255) with RRULE values in it)
If you're having to roll your own recurrence calculator, and you want to keep it simple, limiting your recurrences to daily, weekly, monthly, or yearly covers your first 80% use case and is trivially easy to calc.
At which point your potential recurrence schema looks something like:
id
recurrence_start
recurrence_end
type (daily|weekly|monthly|yearly)
day_of_week (for weekly)
month
day_of_month
And frankly the complex solutions probably aren't worth it :)